1 /* 2 * Copyright 2018 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 18 #define LOG_TAG "VulkanPreTransformTestHelpers" 19 20 #ifndef VK_USE_PLATFORM_ANDROID_KHR 21 #define VK_USE_PLATFORM_ANDROID_KHR 22 #endif 23 24 #include <android/log.h> 25 #include <cstring> 26 27 #include "VulkanPreTransformTestHelpers.h" 28 29 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) 30 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 31 #define ASSERT(a) \ 32 if (!(a)) { \ 33 ALOGE("Failure: " #a " at " __FILE__ ":%d", __LINE__); \ 34 return VK_TEST_ERROR; \ 35 } 36 #define VK_CALL(a) ASSERT(VK_SUCCESS == (a)) 37 38 static const float vertexData[] = { 39 // L:left, T:top, R:right, B:bottom, C:center 40 -1.0f, -1.0f, 0.0f, // LT 41 -1.0f, 0.0f, 0.0f, // LC 42 0.0f, -1.0f, 0.0f, // CT 43 0.0f, 0.0f, 0.0f, // CC 44 1.0f, -1.0f, 0.0f, // RT 45 1.0f, 0.0f, 0.0f, // RC 46 -1.0f, 0.0f, 0.0f, // LC 47 -1.0f, 1.0f, 0.0f, // LB 48 0.0f, 0.0f, 0.0f, // CC 49 0.0f, 1.0f, 0.0f, // CB 50 1.0f, 0.0f, 0.0f, // RC 51 1.0f, 1.0f, 0.0f, // RB 52 }; 53 54 static const float fragData[] = { 55 1.0f, 0.0f, 0.0f, // Red 56 0.0f, 1.0f, 0.0f, // Green 57 0.0f, 0.0f, 1.0f, // Blue 58 1.0f, 1.0f, 0.0f, // Yellow 59 }; 60 61 static const char* requiredInstanceExtensions[] = { 62 "VK_KHR_surface", 63 "VK_KHR_android_surface", 64 }; 65 66 static const char* requiredDeviceExtensions[] = { 67 "VK_KHR_swapchain", 68 }; 69 70 static bool enumerateInstanceExtensions(std::vector<VkExtensionProperties>* extensions) { 71 VkResult result; 72 73 uint32_t count = 0; 74 result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); 75 if (result != VK_SUCCESS) return false; 76 77 extensions->resize(count); 78 result = vkEnumerateInstanceExtensionProperties(nullptr, &count, extensions->data()); 79 if (result != VK_SUCCESS) return false; 80 81 return true; 82 } 83 84 static bool enumerateDeviceExtensions(VkPhysicalDevice device, 85 std::vector<VkExtensionProperties>* extensions) { 86 VkResult result; 87 88 uint32_t count = 0; 89 result = vkEnumerateDeviceExtensionProperties(device, nullptr, &count, nullptr); 90 if (result != VK_SUCCESS) return false; 91 92 extensions->resize(count); 93 result = vkEnumerateDeviceExtensionProperties(device, nullptr, &count, extensions->data()); 94 if (result != VK_SUCCESS) return false; 95 96 return true; 97 } 98 99 static bool hasExtension(const char* extension_name, 100 const std::vector<VkExtensionProperties>& extensions) { 101 return std::find_if(extensions.cbegin(), extensions.cend(), 102 [extension_name](const VkExtensionProperties& extension) { 103 return strcmp(extension.extensionName, extension_name) == 0; 104 }) != extensions.cend(); 105 } 106 107 DeviceInfo::DeviceInfo() 108 : mInstance(VK_NULL_HANDLE), 109 mGpu(VK_NULL_HANDLE), 110 mWindow(nullptr), 111 mSurface(VK_NULL_HANDLE), 112 mQueueFamilyIndex(0), 113 mDevice(VK_NULL_HANDLE), 114 mQueue(VK_NULL_HANDLE) {} 115 116 DeviceInfo::~DeviceInfo() { 117 if (mDevice) { 118 vkDeviceWaitIdle(mDevice); 119 vkDestroyDevice(mDevice, nullptr); 120 mDevice = VK_NULL_HANDLE; 121 } 122 if (mInstance) { 123 vkDestroySurfaceKHR(mInstance, mSurface, nullptr); 124 vkDestroyInstance(mInstance, nullptr); 125 mInstance = VK_NULL_HANDLE; 126 } 127 if (mWindow) { 128 ANativeWindow_release(mWindow); 129 mWindow = nullptr; 130 } 131 } 132 133 VkTestResult DeviceInfo::init(JNIEnv* env, jobject jSurface) { 134 ASSERT(jSurface); 135 136 mWindow = ANativeWindow_fromSurface(env, jSurface); 137 ASSERT(mWindow); 138 139 std::vector<VkExtensionProperties> supportedInstanceExtensions; 140 ASSERT(enumerateInstanceExtensions(&supportedInstanceExtensions)); 141 142 std::vector<const char*> enabledInstanceExtensions; 143 for (const auto extension : requiredInstanceExtensions) { 144 ASSERT(hasExtension(extension, supportedInstanceExtensions)); 145 enabledInstanceExtensions.push_back(extension); 146 } 147 148 const VkApplicationInfo appInfo = { 149 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 150 .pNext = nullptr, 151 .pApplicationName = "VulkanPreTransformTest", 152 .applicationVersion = VK_MAKE_VERSION(1, 0, 0), 153 .pEngineName = "", 154 .engineVersion = VK_MAKE_VERSION(1, 0, 0), 155 .apiVersion = VK_MAKE_VERSION(1, 0, 0), 156 }; 157 const VkInstanceCreateInfo instanceInfo = { 158 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 159 .pNext = nullptr, 160 .flags = 0, 161 .pApplicationInfo = &appInfo, 162 .enabledLayerCount = 0, 163 .ppEnabledLayerNames = nullptr, 164 .enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size()), 165 .ppEnabledExtensionNames = enabledInstanceExtensions.data(), 166 }; 167 VK_CALL(vkCreateInstance(&instanceInfo, nullptr, &mInstance)); 168 169 uint32_t gpuCount = 0; 170 VK_CALL(vkEnumeratePhysicalDevices(mInstance, &gpuCount, nullptr)); 171 if (gpuCount == 0) { 172 ALOGD("No physical device available"); 173 return VK_TEST_PHYSICAL_DEVICE_NOT_EXISTED; 174 } 175 176 std::vector<VkPhysicalDevice> gpus(gpuCount, VK_NULL_HANDLE); 177 VK_CALL(vkEnumeratePhysicalDevices(mInstance, &gpuCount, gpus.data())); 178 179 mGpu = gpus[0]; 180 181 const VkAndroidSurfaceCreateInfoKHR surfaceInfo = { 182 .sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, 183 .pNext = nullptr, 184 .flags = 0, 185 .window = mWindow, 186 }; 187 VK_CALL(vkCreateAndroidSurfaceKHR(mInstance, &surfaceInfo, nullptr, &mSurface)); 188 189 std::vector<VkExtensionProperties> supportedDeviceExtensions; 190 ASSERT(enumerateDeviceExtensions(mGpu, &supportedDeviceExtensions)); 191 192 std::vector<const char*> enabledDeviceExtensions; 193 for (const auto extension : requiredDeviceExtensions) { 194 ASSERT(hasExtension(extension, supportedDeviceExtensions)); 195 enabledDeviceExtensions.push_back(extension); 196 } 197 198 uint32_t queueFamilyCount = 0; 199 vkGetPhysicalDeviceQueueFamilyProperties(mGpu, &queueFamilyCount, nullptr); 200 ASSERT(queueFamilyCount); 201 202 std::vector<VkQueueFamilyProperties> queueFamilyProperties(queueFamilyCount); 203 vkGetPhysicalDeviceQueueFamilyProperties(mGpu, &queueFamilyCount, queueFamilyProperties.data()); 204 205 uint32_t queueFamilyIndex; 206 for (queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; ++queueFamilyIndex) { 207 if (queueFamilyProperties[queueFamilyIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) { 208 break; 209 } 210 } 211 ASSERT(queueFamilyIndex < queueFamilyCount); 212 mQueueFamilyIndex = queueFamilyIndex; 213 214 VkBool32 supported = VK_FALSE; 215 VK_CALL(vkGetPhysicalDeviceSurfaceSupportKHR(mGpu, mQueueFamilyIndex, mSurface, &supported)); 216 if (supported == VK_FALSE) { 217 ALOGD("Surface format not supported"); 218 return VK_TEST_SURFACE_FORMAT_NOT_SUPPORTED; 219 } 220 221 const float priority = 1.0f; 222 const VkDeviceQueueCreateInfo queueCreateInfo = { 223 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 224 .pNext = nullptr, 225 .flags = 0, 226 .queueFamilyIndex = mQueueFamilyIndex, 227 .queueCount = 1, 228 .pQueuePriorities = &priority, 229 }; 230 const VkDeviceCreateInfo deviceCreateInfo = { 231 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 232 .pNext = nullptr, 233 .queueCreateInfoCount = 1, 234 .pQueueCreateInfos = &queueCreateInfo, 235 .enabledLayerCount = 0, 236 .ppEnabledLayerNames = nullptr, 237 .enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size()), 238 .ppEnabledExtensionNames = enabledDeviceExtensions.data(), 239 .pEnabledFeatures = nullptr, 240 }; 241 VK_CALL(vkCreateDevice(mGpu, &deviceCreateInfo, nullptr, &mDevice)); 242 243 vkGetDeviceQueue(mDevice, mQueueFamilyIndex, 0, &mQueue); 244 245 return VK_TEST_SUCCESS; 246 } 247 248 SwapchainInfo::SwapchainInfo(const DeviceInfo* const deviceInfo) 249 : mDeviceInfo(deviceInfo), 250 mFormat(VK_FORMAT_UNDEFINED), 251 mDisplaySize({0, 0}), 252 mSwapchain(VK_NULL_HANDLE), 253 mSwapchainLength(0) {} 254 255 SwapchainInfo::~SwapchainInfo() { 256 if (mDeviceInfo->device()) { 257 vkDeviceWaitIdle(mDeviceInfo->device()); 258 vkDestroySwapchainKHR(mDeviceInfo->device(), mSwapchain, nullptr); 259 } 260 } 261 262 VkTestResult SwapchainInfo::init(bool setPreTransform, int* outPreTransformHint) { 263 VkSurfaceCapabilitiesKHR surfaceCapabilities; 264 VK_CALL(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(mDeviceInfo->gpu(), mDeviceInfo->surface(), 265 &surfaceCapabilities)); 266 ALOGD("Vulkan Surface Capabilities:\n"); 267 ALOGD("\timage count: %u - %u\n", surfaceCapabilities.minImageCount, 268 surfaceCapabilities.maxImageCount); 269 ALOGD("\tarray layers: %u\n", surfaceCapabilities.maxImageArrayLayers); 270 ALOGD("\timage size (now): %dx%d\n", surfaceCapabilities.currentExtent.width, 271 surfaceCapabilities.currentExtent.height); 272 ALOGD("\timage size (extent): %dx%d - %dx%d\n", surfaceCapabilities.minImageExtent.width, 273 surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.width, 274 surfaceCapabilities.maxImageExtent.height); 275 ALOGD("\tusage: %x\n", surfaceCapabilities.supportedUsageFlags); 276 ALOGD("\tcurrent transform: %u\n", surfaceCapabilities.currentTransform); 277 ALOGD("\tallowed transforms: %x\n", surfaceCapabilities.supportedTransforms); 278 ALOGD("\tcomposite alpha flags: %u\n", surfaceCapabilities.supportedCompositeAlpha); 279 280 uint32_t formatCount = 0; 281 VK_CALL(vkGetPhysicalDeviceSurfaceFormatsKHR(mDeviceInfo->gpu(), mDeviceInfo->surface(), 282 &formatCount, nullptr)); 283 284 std::vector<VkSurfaceFormatKHR> formats(formatCount); 285 VK_CALL(vkGetPhysicalDeviceSurfaceFormatsKHR(mDeviceInfo->gpu(), mDeviceInfo->surface(), 286 &formatCount, formats.data())); 287 288 uint32_t formatIndex; 289 for (formatIndex = 0; formatIndex < formatCount; ++formatIndex) { 290 if (formats[formatIndex].format == VK_FORMAT_R8G8B8A8_UNORM) { 291 break; 292 } 293 } 294 ASSERT(formatIndex < formatCount); 295 296 mFormat = formats[formatIndex].format; 297 mDisplaySize = surfaceCapabilities.currentExtent; 298 299 VkSurfaceTransformFlagBitsKHR preTransform = 300 (setPreTransform ? surfaceCapabilities.currentTransform 301 : VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR); 302 ALOGD("currentTransform = %u, preTransform = %u", 303 static_cast<uint32_t>(surfaceCapabilities.currentTransform), 304 static_cast<uint32_t>(preTransform)); 305 306 if ((preTransform & 307 (VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR | VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR | 308 VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR | 309 VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR)) != 0) { 310 std::swap(mDisplaySize.width, mDisplaySize.height); 311 } 312 313 if (outPreTransformHint) { 314 *outPreTransformHint = surfaceCapabilities.currentTransform; 315 } 316 317 const uint32_t queueFamilyIndex = mDeviceInfo->queueFamilyIndex(); 318 const VkSwapchainCreateInfoKHR swapchainCreateInfo = { 319 .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, 320 .pNext = nullptr, 321 .flags = 0, 322 .surface = mDeviceInfo->surface(), 323 .minImageCount = surfaceCapabilities.minImageCount, 324 .imageFormat = mFormat, 325 .imageColorSpace = formats[formatIndex].colorSpace, 326 .imageExtent = mDisplaySize, 327 .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 328 .preTransform = preTransform, 329 .imageArrayLayers = 1, 330 .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, 331 .queueFamilyIndexCount = 1, 332 .pQueueFamilyIndices = &queueFamilyIndex, 333 .compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, 334 .presentMode = VK_PRESENT_MODE_FIFO_KHR, 335 .clipped = VK_FALSE, 336 }; 337 VK_CALL(vkCreateSwapchainKHR(mDeviceInfo->device(), &swapchainCreateInfo, nullptr, 338 &mSwapchain)); 339 340 VK_CALL(vkGetSwapchainImagesKHR(mDeviceInfo->device(), mSwapchain, &mSwapchainLength, nullptr)); 341 ALOGD("Swapchain length = %u", mSwapchainLength); 342 343 return VK_TEST_SUCCESS; 344 } 345 346 Renderer::Renderer(const DeviceInfo* const deviceInfo, const SwapchainInfo* const swapchainInfo) 347 : mDeviceInfo(deviceInfo), 348 mSwapchainInfo(swapchainInfo), 349 mDeviceMemory(VK_NULL_HANDLE), 350 mVertexBuffer(VK_NULL_HANDLE), 351 mRenderPass(VK_NULL_HANDLE), 352 mVertexShader(VK_NULL_HANDLE), 353 mFragmentShader(VK_NULL_HANDLE), 354 mPipelineLayout(VK_NULL_HANDLE), 355 mPipeline(VK_NULL_HANDLE), 356 mCommandPool(VK_NULL_HANDLE), 357 mSemaphore(VK_NULL_HANDLE), 358 mFence(VK_NULL_HANDLE) {} 359 360 Renderer::~Renderer() { 361 if (mDeviceInfo->device()) { 362 vkDeviceWaitIdle(mDeviceInfo->device()); 363 vkDestroyShaderModule(mDeviceInfo->device(), mVertexShader, nullptr); 364 vkDestroyShaderModule(mDeviceInfo->device(), mFragmentShader, nullptr); 365 vkDestroyFence(mDeviceInfo->device(), mFence, nullptr); 366 vkDestroySemaphore(mDeviceInfo->device(), mSemaphore, nullptr); 367 if (!mCommandBuffers.empty()) { 368 vkFreeCommandBuffers(mDeviceInfo->device(), mCommandPool, mCommandBuffers.size(), 369 mCommandBuffers.data()); 370 } 371 vkDestroyCommandPool(mDeviceInfo->device(), mCommandPool, nullptr); 372 vkDestroyPipeline(mDeviceInfo->device(), mPipeline, nullptr); 373 vkDestroyPipelineLayout(mDeviceInfo->device(), mPipelineLayout, nullptr); 374 vkDestroyBuffer(mDeviceInfo->device(), mVertexBuffer, nullptr); 375 vkFreeMemory(mDeviceInfo->device(), mDeviceMemory, nullptr); 376 vkDestroyRenderPass(mDeviceInfo->device(), mRenderPass, nullptr); 377 for (auto& framebuffer : mFramebuffers) { 378 vkDestroyFramebuffer(mDeviceInfo->device(), framebuffer, nullptr); 379 } 380 for (auto& imageView : mImageViews) { 381 vkDestroyImageView(mDeviceInfo->device(), imageView, nullptr); 382 } 383 } 384 } 385 386 VkTestResult Renderer::createRenderPass() { 387 const VkAttachmentDescription attachmentDescription = { 388 .flags = 0, 389 .format = mSwapchainInfo->format(), 390 .samples = VK_SAMPLE_COUNT_1_BIT, 391 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, 392 .storeOp = VK_ATTACHMENT_STORE_OP_STORE, 393 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, 394 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, 395 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, 396 .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 397 }; 398 const VkAttachmentReference attachmentReference = { 399 .attachment = 0, 400 .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 401 }; 402 const VkSubpassDescription subpassDescription = { 403 .flags = 0, 404 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, 405 .inputAttachmentCount = 0, 406 .pInputAttachments = nullptr, 407 .colorAttachmentCount = 1, 408 .pColorAttachments = &attachmentReference, 409 .pResolveAttachments = nullptr, 410 .pDepthStencilAttachment = nullptr, 411 .preserveAttachmentCount = 0, 412 .pPreserveAttachments = nullptr, 413 }; 414 const VkRenderPassCreateInfo renderPassCreateInfo = { 415 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 416 .pNext = nullptr, 417 .flags = 0, 418 .attachmentCount = 1, 419 .pAttachments = &attachmentDescription, 420 .subpassCount = 1, 421 .pSubpasses = &subpassDescription, 422 .dependencyCount = 0, 423 .pDependencies = nullptr, 424 }; 425 VK_CALL(vkCreateRenderPass(mDeviceInfo->device(), &renderPassCreateInfo, nullptr, 426 &mRenderPass)); 427 428 return VK_TEST_SUCCESS; 429 } 430 431 VkTestResult Renderer::createFrameBuffers() { 432 uint32_t swapchainLength = mSwapchainInfo->swapchainLength(); 433 std::vector<VkImage> images(swapchainLength, VK_NULL_HANDLE); 434 VK_CALL(vkGetSwapchainImagesKHR(mDeviceInfo->device(), mSwapchainInfo->swapchain(), 435 &swapchainLength, images.data())); 436 437 mImageViews.resize(swapchainLength, VK_NULL_HANDLE); 438 for (uint32_t i = 0; i < swapchainLength; ++i) { 439 const VkImageViewCreateInfo imageViewCreateInfo = { 440 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 441 .pNext = nullptr, 442 .flags = 0, 443 .image = images[i], 444 .viewType = VK_IMAGE_VIEW_TYPE_2D, 445 .format = mSwapchainInfo->format(), 446 .components = 447 { 448 .r = VK_COMPONENT_SWIZZLE_R, 449 .g = VK_COMPONENT_SWIZZLE_G, 450 .b = VK_COMPONENT_SWIZZLE_B, 451 .a = VK_COMPONENT_SWIZZLE_A, 452 }, 453 .subresourceRange = 454 { 455 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 456 .baseMipLevel = 0, 457 .levelCount = 1, 458 .baseArrayLayer = 0, 459 .layerCount = 1, 460 }, 461 }; 462 VK_CALL(vkCreateImageView(mDeviceInfo->device(), &imageViewCreateInfo, nullptr, 463 &mImageViews[i])); 464 } 465 466 mFramebuffers.resize(swapchainLength, VK_NULL_HANDLE); 467 for (uint32_t i = 0; i < swapchainLength; ++i) { 468 const VkFramebufferCreateInfo framebufferCreateInfo = { 469 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 470 .pNext = nullptr, 471 .flags = 0, 472 .renderPass = mRenderPass, 473 .attachmentCount = 1, 474 .pAttachments = &mImageViews[i], 475 .width = mSwapchainInfo->displaySize().width, 476 .height = mSwapchainInfo->displaySize().height, 477 .layers = 1, 478 }; 479 VK_CALL(vkCreateFramebuffer(mDeviceInfo->device(), &framebufferCreateInfo, nullptr, 480 &mFramebuffers[i])); 481 } 482 483 return VK_TEST_SUCCESS; 484 } 485 486 VkTestResult Renderer::createVertexBuffers() { 487 const uint32_t queueFamilyIndex = mDeviceInfo->queueFamilyIndex(); 488 const VkBufferCreateInfo bufferCreateInfo = { 489 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 490 .pNext = nullptr, 491 .flags = 0, 492 .size = sizeof(vertexData), 493 .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, 494 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 495 .queueFamilyIndexCount = 1, 496 .pQueueFamilyIndices = &queueFamilyIndex, 497 }; 498 VK_CALL(vkCreateBuffer(mDeviceInfo->device(), &bufferCreateInfo, nullptr, &mVertexBuffer)); 499 500 VkMemoryRequirements memoryRequirements; 501 vkGetBufferMemoryRequirements(mDeviceInfo->device(), mVertexBuffer, &memoryRequirements); 502 503 VkPhysicalDeviceMemoryProperties memoryProperties; 504 vkGetPhysicalDeviceMemoryProperties(mDeviceInfo->gpu(), &memoryProperties); 505 506 int32_t typeIndex = -1; 507 for (int32_t i = 0, typeBits = memoryRequirements.memoryTypeBits; i < 32; ++i) { 508 if ((typeBits & 1) == 1) { 509 if ((memoryProperties.memoryTypes[i].propertyFlags & 510 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { 511 typeIndex = i; 512 break; 513 } 514 } 515 typeBits >>= 1; 516 } 517 ASSERT(typeIndex != -1); 518 519 VkMemoryAllocateInfo memoryAllocateInfo = { 520 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 521 .pNext = nullptr, 522 .allocationSize = memoryRequirements.size, 523 .memoryTypeIndex = static_cast<uint32_t>(typeIndex), 524 }; 525 VK_CALL(vkAllocateMemory(mDeviceInfo->device(), &memoryAllocateInfo, nullptr, &mDeviceMemory)); 526 527 void* data; 528 VK_CALL(vkMapMemory(mDeviceInfo->device(), mDeviceMemory, 0, sizeof(vertexData), 0, &data)); 529 530 memcpy(data, vertexData, sizeof(vertexData)); 531 vkUnmapMemory(mDeviceInfo->device(), mDeviceMemory); 532 533 VK_CALL(vkBindBufferMemory(mDeviceInfo->device(), mVertexBuffer, mDeviceMemory, 0)); 534 535 return VK_TEST_SUCCESS; 536 } 537 538 VkTestResult Renderer::loadShaderFromFile(const char* filePath, VkShaderModule* const outShader) { 539 ASSERT(filePath); 540 541 AAsset* file = AAssetManager_open(mAssetManager, filePath, AASSET_MODE_BUFFER); 542 ASSERT(file); 543 544 size_t fileLength = AAsset_getLength(file); 545 std::vector<char> fileContent(fileLength); 546 AAsset_read(file, fileContent.data(), fileLength); 547 AAsset_close(file); 548 549 const VkShaderModuleCreateInfo shaderModuleCreateInfo = { 550 .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 551 .pNext = nullptr, 552 .flags = 0, 553 .codeSize = fileLength, 554 .pCode = (const uint32_t*)(fileContent.data()), 555 }; 556 VK_CALL(vkCreateShaderModule(mDeviceInfo->device(), &shaderModuleCreateInfo, nullptr, 557 outShader)); 558 559 return VK_TEST_SUCCESS; 560 } 561 562 VkTestResult Renderer::createGraphicsPipeline() { 563 const VkPushConstantRange pushConstantRange = { 564 .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, 565 .offset = 0, 566 .size = 3 * sizeof(float), 567 }; 568 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = { 569 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 570 .pNext = nullptr, 571 .flags = 0, 572 .setLayoutCount = 0, 573 .pSetLayouts = nullptr, 574 .pushConstantRangeCount = 1, 575 .pPushConstantRanges = &pushConstantRange, 576 }; 577 VK_CALL(vkCreatePipelineLayout(mDeviceInfo->device(), &pipelineLayoutCreateInfo, nullptr, 578 &mPipelineLayout)); 579 580 ASSERT(!loadShaderFromFile("shaders/tri.vert.spv", &mVertexShader)); 581 ASSERT(!loadShaderFromFile("shaders/tri.frag.spv", &mFragmentShader)); 582 583 const VkPipelineShaderStageCreateInfo shaderStages[2] = 584 {{ 585 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 586 .pNext = nullptr, 587 .flags = 0, 588 .stage = VK_SHADER_STAGE_VERTEX_BIT, 589 .module = mVertexShader, 590 .pName = "main", 591 .pSpecializationInfo = nullptr, 592 }, 593 { 594 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 595 .pNext = nullptr, 596 .flags = 0, 597 .stage = VK_SHADER_STAGE_FRAGMENT_BIT, 598 .module = mFragmentShader, 599 .pName = "main", 600 .pSpecializationInfo = nullptr, 601 }}; 602 const VkViewport viewports = { 603 .x = 0.0f, 604 .y = 0.0f, 605 .width = (float)mSwapchainInfo->displaySize().width, 606 .height = (float)mSwapchainInfo->displaySize().height, 607 .minDepth = 0.0f, 608 .maxDepth = 1.0f, 609 }; 610 const VkRect2D scissor = { 611 .offset = 612 { 613 .x = 0, 614 .y = 0, 615 }, 616 .extent = mSwapchainInfo->displaySize(), 617 }; 618 const VkPipelineViewportStateCreateInfo viewportInfo = { 619 .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 620 .pNext = nullptr, 621 .flags = 0, 622 .viewportCount = 1, 623 .pViewports = &viewports, 624 .scissorCount = 1, 625 .pScissors = &scissor, 626 }; 627 VkSampleMask sampleMask = ~0u; 628 const VkPipelineMultisampleStateCreateInfo multisampleInfo = { 629 .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 630 .pNext = nullptr, 631 .flags = 0, 632 .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, 633 .sampleShadingEnable = VK_FALSE, 634 .minSampleShading = 0, 635 .pSampleMask = &sampleMask, 636 .alphaToCoverageEnable = VK_FALSE, 637 .alphaToOneEnable = VK_FALSE, 638 }; 639 const VkPipelineColorBlendAttachmentState attachmentStates = { 640 .blendEnable = VK_FALSE, 641 .srcColorBlendFactor = (VkBlendFactor)0, 642 .dstColorBlendFactor = (VkBlendFactor)0, 643 .colorBlendOp = (VkBlendOp)0, 644 .srcAlphaBlendFactor = (VkBlendFactor)0, 645 .dstAlphaBlendFactor = (VkBlendFactor)0, 646 .alphaBlendOp = (VkBlendOp)0, 647 .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | 648 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, 649 }; 650 const VkPipelineColorBlendStateCreateInfo colorBlendInfo = { 651 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 652 .pNext = nullptr, 653 .flags = 0, 654 .logicOpEnable = VK_FALSE, 655 .logicOp = VK_LOGIC_OP_COPY, 656 .attachmentCount = 1, 657 .pAttachments = &attachmentStates, 658 .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, 659 }; 660 const VkPipelineRasterizationStateCreateInfo rasterInfo = { 661 .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 662 .pNext = nullptr, 663 .flags = 0, 664 .depthClampEnable = VK_FALSE, 665 .rasterizerDiscardEnable = VK_FALSE, 666 .polygonMode = VK_POLYGON_MODE_FILL, 667 .cullMode = VK_CULL_MODE_NONE, 668 .frontFace = VK_FRONT_FACE_CLOCKWISE, 669 .depthBiasEnable = VK_FALSE, 670 .depthBiasConstantFactor = 0, 671 .depthBiasClamp = 0, 672 .depthBiasSlopeFactor = 0, 673 .lineWidth = 1, 674 }; 675 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = { 676 .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 677 .pNext = nullptr, 678 .flags = 0, 679 .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 680 .primitiveRestartEnable = VK_FALSE, 681 }; 682 const VkVertexInputBindingDescription vertexInputBindingDescription = { 683 .binding = 0, 684 .stride = 3 * sizeof(float), 685 .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, 686 }; 687 const VkVertexInputAttributeDescription vertexInputAttributeDescription = { 688 .location = 0, 689 .binding = 0, 690 .format = VK_FORMAT_R32G32B32_SFLOAT, 691 .offset = 0, 692 }; 693 const VkPipelineVertexInputStateCreateInfo vertexInputInfo = { 694 .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 695 .pNext = nullptr, 696 .flags = 0, 697 .vertexBindingDescriptionCount = 1, 698 .pVertexBindingDescriptions = &vertexInputBindingDescription, 699 .vertexAttributeDescriptionCount = 1, 700 .pVertexAttributeDescriptions = &vertexInputAttributeDescription, 701 }; 702 const VkGraphicsPipelineCreateInfo pipelineCreateInfo = { 703 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 704 .pNext = nullptr, 705 .flags = 0, 706 .stageCount = 2, 707 .pStages = shaderStages, 708 .pVertexInputState = &vertexInputInfo, 709 .pInputAssemblyState = &inputAssemblyInfo, 710 .pTessellationState = nullptr, 711 .pViewportState = &viewportInfo, 712 .pRasterizationState = &rasterInfo, 713 .pMultisampleState = &multisampleInfo, 714 .pDepthStencilState = nullptr, 715 .pColorBlendState = &colorBlendInfo, 716 .pDynamicState = nullptr, 717 .layout = mPipelineLayout, 718 .renderPass = mRenderPass, 719 .subpass = 0, 720 .basePipelineHandle = VK_NULL_HANDLE, 721 .basePipelineIndex = 0, 722 }; 723 VK_CALL(vkCreateGraphicsPipelines(mDeviceInfo->device(), VK_NULL_HANDLE, 1, &pipelineCreateInfo, 724 nullptr, &mPipeline)); 725 726 vkDestroyShaderModule(mDeviceInfo->device(), mVertexShader, nullptr); 727 vkDestroyShaderModule(mDeviceInfo->device(), mFragmentShader, nullptr); 728 mVertexShader = VK_NULL_HANDLE; 729 mFragmentShader = VK_NULL_HANDLE; 730 731 return VK_TEST_SUCCESS; 732 } 733 734 VkTestResult Renderer::init(JNIEnv* env, jobject jAssetManager) { 735 mAssetManager = AAssetManager_fromJava(env, jAssetManager); 736 ASSERT(mAssetManager); 737 738 ASSERT(!createRenderPass()); 739 740 ASSERT(!createFrameBuffers()); 741 742 ASSERT(!createVertexBuffers()); 743 744 ASSERT(!createGraphicsPipeline()); 745 746 const VkCommandPoolCreateInfo commandPoolCreateInfo = { 747 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 748 .pNext = nullptr, 749 .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, 750 .queueFamilyIndex = mDeviceInfo->queueFamilyIndex(), 751 }; 752 VK_CALL(vkCreateCommandPool(mDeviceInfo->device(), &commandPoolCreateInfo, nullptr, 753 &mCommandPool)); 754 755 uint32_t swapchainLength = mSwapchainInfo->swapchainLength(); 756 mCommandBuffers.resize(swapchainLength, VK_NULL_HANDLE); 757 const VkCommandBufferAllocateInfo commandBufferAllocateInfo = { 758 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 759 .pNext = nullptr, 760 .commandPool = mCommandPool, 761 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 762 .commandBufferCount = swapchainLength, 763 }; 764 VK_CALL(vkAllocateCommandBuffers(mDeviceInfo->device(), &commandBufferAllocateInfo, 765 mCommandBuffers.data())); 766 767 for (uint32_t i = 0; i < swapchainLength; ++i) { 768 const VkCommandBufferBeginInfo commandBufferBeginInfo = { 769 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 770 .pNext = nullptr, 771 .flags = 0, 772 .pInheritanceInfo = nullptr, 773 }; 774 VK_CALL(vkBeginCommandBuffer(mCommandBuffers[i], &commandBufferBeginInfo)); 775 776 const VkClearValue clearVals = { 777 .color.float32[0] = 0.0f, 778 .color.float32[1] = 0.0f, 779 .color.float32[2] = 0.0f, 780 .color.float32[3] = 1.0f, 781 }; 782 const VkRenderPassBeginInfo renderPassBeginInfo = { 783 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 784 .pNext = nullptr, 785 .renderPass = mRenderPass, 786 .framebuffer = mFramebuffers[i], 787 .renderArea = 788 { 789 .offset = 790 { 791 .x = 0, 792 .y = 0, 793 }, 794 .extent = mSwapchainInfo->displaySize(), 795 }, 796 .clearValueCount = 1, 797 .pClearValues = &clearVals, 798 }; 799 vkCmdBeginRenderPass(mCommandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 800 801 vkCmdBindPipeline(mCommandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, mPipeline); 802 803 VkDeviceSize offset = 0; 804 vkCmdBindVertexBuffers(mCommandBuffers[i], 0, 1, &mVertexBuffer, &offset); 805 806 vkCmdPushConstants(mCommandBuffers[i], mPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, 807 3 * sizeof(float), &fragData[0]); 808 vkCmdDraw(mCommandBuffers[i], 4, 1, 0, 0); 809 810 vkCmdPushConstants(mCommandBuffers[i], mPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, 811 3 * sizeof(float), &fragData[3]); 812 vkCmdDraw(mCommandBuffers[i], 4, 1, 2, 0); 813 814 vkCmdPushConstants(mCommandBuffers[i], mPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, 815 3 * sizeof(float), &fragData[6]); 816 vkCmdDraw(mCommandBuffers[i], 4, 1, 6, 0); 817 818 vkCmdPushConstants(mCommandBuffers[i], mPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, 819 3 * sizeof(float), &fragData[9]); 820 vkCmdDraw(mCommandBuffers[i], 4, 1, 8, 0); 821 822 vkCmdEndRenderPass(mCommandBuffers[i]); 823 824 VK_CALL(vkEndCommandBuffer(mCommandBuffers[i])); 825 } 826 827 const VkFenceCreateInfo fenceCreateInfo = { 828 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 829 .pNext = nullptr, 830 .flags = 0, 831 }; 832 VK_CALL(vkCreateFence(mDeviceInfo->device(), &fenceCreateInfo, nullptr, &mFence)); 833 834 const VkSemaphoreCreateInfo semaphoreCreateInfo = { 835 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, 836 .pNext = nullptr, 837 .flags = 0, 838 }; 839 VK_CALL(vkCreateSemaphore(mDeviceInfo->device(), &semaphoreCreateInfo, nullptr, &mSemaphore)); 840 841 return VK_TEST_SUCCESS; 842 } 843 844 VkTestResult Renderer::drawFrame() { 845 uint32_t nextIndex; 846 VK_CALL(vkAcquireNextImageKHR(mDeviceInfo->device(), mSwapchainInfo->swapchain(), UINT64_MAX, 847 mSemaphore, VK_NULL_HANDLE, &nextIndex)); 848 849 VK_CALL(vkResetFences(mDeviceInfo->device(), 1, &mFence)); 850 851 VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 852 const VkSubmitInfo submitInfo = { 853 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 854 .pNext = nullptr, 855 .waitSemaphoreCount = 1, 856 .pWaitSemaphores = &mSemaphore, 857 .pWaitDstStageMask = &waitStageMask, 858 .commandBufferCount = 1, 859 .pCommandBuffers = &mCommandBuffers[nextIndex], 860 .signalSemaphoreCount = 0, 861 .pSignalSemaphores = nullptr, 862 }; 863 VK_CALL(vkQueueSubmit(mDeviceInfo->queue(), 1, &submitInfo, mFence)) 864 865 VK_CALL(vkWaitForFences(mDeviceInfo->device(), 1, &mFence, VK_TRUE, 100000000)); 866 867 const VkSwapchainKHR swapchain = mSwapchainInfo->swapchain(); 868 const VkPresentInfoKHR presentInfo = { 869 .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 870 .pNext = nullptr, 871 .waitSemaphoreCount = 0, 872 .pWaitSemaphores = nullptr, 873 .swapchainCount = 1, 874 .pSwapchains = &swapchain, 875 .pImageIndices = &nextIndex, 876 .pResults = nullptr, 877 }; 878 VkResult ret = vkQueuePresentKHR(mDeviceInfo->queue(), &presentInfo); 879 if (ret == VK_SUBOPTIMAL_KHR) { 880 return VK_TEST_SUCCESS_SUBOPTIMAL; 881 } 882 883 return ret == VK_SUCCESS ? VK_TEST_SUCCESS : VK_TEST_ERROR; 884 } 885