25 #define PNG_SWAPCHAIN_IMAGES 3 27 #ifdef FORCE_NO_VALIDATION 28 #define ENABLE_VALIDATION_LAYERS 0 30 #define ENABLE_VALIDATION_LAYERS 1 38 static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT type,
39 uint64_t
object,
size_t location, int32_t messageCode,
40 const char *pLayerPrefix,
const char *pMessage,
void *pUserData)
42 auto *platform =
static_cast<PNGPlatform *
>(pUserData);
43 auto callback = platform->getExternalDebugCallback();
47 return callback(flags, type,
object, location, messageCode, pLayerPrefix, pMessage,
48 platform->getExternalDebugCallbackUserData());
52 if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
54 LOGE(
"Validation Layer: Error: %s: %s\n", pLayerPrefix, pMessage);
56 else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT)
58 LOGE(
"Validation Layer: Warning: %s: %s\n", pLayerPrefix, pMessage);
60 else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
62 LOGI(
"Validation Layer: Performance warning: %s: %s\n", pLayerPrefix, pMessage);
66 LOGI(
"Validation Layer: Information: %s: %s\n", pLayerPrefix, pMessage);
72 uint32_t PNGPlatform::findMemoryTypeFromRequirements(uint32_t deviceRequirements, uint32_t hostRequirements)
74 const VkPhysicalDeviceMemoryProperties &props = memoryProperties;
75 for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++)
77 if (deviceRequirements & (1u << i))
79 if ((props.memoryTypes[i].propertyFlags & hostRequirements) == hostRequirements)
86 LOGE(
"Failed to obtain suitable memory type.\n");
90 uint32_t PNGPlatform::findMemoryTypeFromRequirementsFallback(uint32_t deviceRequirements, uint32_t hostRequirements,
91 uint32_t hostRequirementsFallback)
93 const VkPhysicalDeviceMemoryProperties &props = memoryProperties;
94 for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++)
96 if (deviceRequirements & (1u << i))
98 if ((props.memoryTypes[i].propertyFlags & hostRequirements) == hostRequirements)
105 return findMemoryTypeFromRequirements(deviceRequirements, hostRequirementsFallback);
108 Platform &Platform::get()
112 static PNGPlatform singleton;
118 return STATUS_RUNNING;
121 Result PNGPlatform::initialize()
123 const char *path = getenv(
"MALI_PNG_PATH");
126 LOGI(
"MALI_PNG_PATH environment variable not defined, falling back to " 128 path =
"Mali-SDK-Frames";
130 LOGI(
"Dumping PNG files to: %s.xxxxxxxx.png.\n", path);
134 return RESULT_ERROR_OUT_OF_MEMORY;
137 if (FAILED(pngSwapchain->init(path, PNG_SWAPCHAIN_IMAGES)))
138 return RESULT_ERROR_GENERIC;
142 return RESULT_ERROR_OUT_OF_MEMORY;
144 return RESULT_SUCCESS;
147 void PNGPlatform::terminate()
151 vkDeviceWaitIdle(device);
155 pngSwapchain =
nullptr;
157 for (
auto &image : swapchainImages)
158 if (image != VK_NULL_HANDLE)
159 vkDestroyImage(device, image,
nullptr);
161 for (
auto &memory : swapchainMemory)
162 if (memory != VK_NULL_HANDLE)
163 vkFreeMemory(device, memory,
nullptr);
165 for (
auto &buffer : swapchainReadback)
166 if (buffer != VK_NULL_HANDLE)
167 vkDestroyBuffer(device, buffer,
nullptr);
169 for (
auto &memory : swapchainReadbackMemory)
170 if (memory != VK_NULL_HANDLE)
171 vkFreeMemory(device, memory,
nullptr);
180 vkDestroyDevice(device,
nullptr);
184 VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_EXTENSION_SYMBOL(instance, vkDestroyDebugReportCallbackEXT);
185 vkDestroyDebugReportCallbackEXT(instance, debug_callback,
nullptr);
189 vkDestroyInstance(instance,
nullptr);
191 swapchainImages.clear();
192 swapchainMemory.clear();
193 swapchainReadback.clear();
194 swapchainReadbackMemory.clear();
195 device = VK_NULL_HANDLE;
196 debug_callback = VK_NULL_HANDLE;
197 instance = VK_NULL_HANDLE;
200 PNGPlatform::~PNGPlatform()
208 1280, 720, VK_FORMAT_R8G8B8A8_UNORM,
216 return initVulkan(swapchain);
221 *images = swapchainImages;
222 *swapchain = swapchainDimensions;
225 unsigned PNGPlatform::getNumSwapchainImages()
const 227 return swapchainImages.size();
230 Result PNGPlatform::acquireNextImage(
unsigned *image)
235 *image = pngSwapchain->acquire();
239 pContext->beginFrame(*image, VK_NULL_HANDLE);
240 return RESULT_SUCCESS;
243 void PNGPlatform::imageMemoryBarrier(VkCommandBuffer cmd, VkImage image, VkAccessFlags srcAccessMask,
244 VkAccessFlags dstAccessMask, VkPipelineStageFlags srcStageMask,
245 VkPipelineStageFlags dstStageMask, VkImageLayout oldLayout,
246 VkImageLayout newLayout)
248 VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
250 barrier.srcAccessMask = srcAccessMask;
251 barrier.dstAccessMask = dstAccessMask;
252 barrier.oldLayout = oldLayout;
253 barrier.newLayout = newLayout;
254 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
255 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
256 barrier.image = image;
257 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
258 barrier.subresourceRange.levelCount = 1;
259 barrier.subresourceRange.layerCount = 1;
261 vkCmdPipelineBarrier(cmd, srcStageMask, dstStageMask,
false, 0,
nullptr, 0,
nullptr, 1, &barrier);
264 Result PNGPlatform::presentImage(
unsigned index)
266 auto cmd = pContext->requestPrimaryCommandBuffer();
268 VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
269 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
270 vkBeginCommandBuffer(cmd, &beginInfo);
273 imageMemoryBarrier(cmd, swapchainImages[index], VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT,
274 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
275 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
278 VkBufferImageCopy region = { 0 };
279 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
280 region.imageSubresource.layerCount = 1;
281 region.imageExtent.width = swapchainDimensions.width;
282 region.imageExtent.height = swapchainDimensions.height;
283 region.imageExtent.depth = 1;
284 vkCmdCopyImageToBuffer(cmd, swapchainImages[index], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, swapchainReadback[index],
287 VK_CHECK(vkEndCommandBuffer(cmd));
288 pContext->submit(cmd);
294 unsigned numFences = pContext->getFenceManager().getActiveFenceCount();
295 VkFence *fences = pContext->getFenceManager().getActiveFences();
296 pngSwapchain->present(index, device, swapchainReadbackMemory[index], swapchainDimensions.width,
297 swapchainDimensions.height, numFences, fences, swapchainCoherent);
298 return RESULT_SUCCESS;
303 if (!vulkanSymbolWrapperInitLoader())
305 LOGE(
"Cannot find Vulkan loader.\n");
306 return RESULT_ERROR_GENERIC;
309 if (!vulkanSymbolWrapperLoadGlobalSymbols())
311 LOGE(
"Failed to load global Vulkan symbols.\n");
312 return RESULT_ERROR_GENERIC;
315 uint32_t instanceExtensionCount;
316 VK_CHECK(vkEnumerateInstanceExtensionProperties(
nullptr, &instanceExtensionCount,
nullptr));
317 vector<VkExtensionProperties> instanceExtensions(instanceExtensionCount);
318 VK_CHECK(vkEnumerateInstanceExtensionProperties(
nullptr, &instanceExtensionCount, instanceExtensions.data()));
320 for (
auto &instanceExt : instanceExtensions)
321 LOGI(
"Instance extension: %s\n", instanceExt.extensionName);
323 #if ENABLE_VALIDATION_LAYERS 324 uint32_t instanceLayerCount;
325 VK_CHECK(vkEnumerateInstanceLayerProperties(&instanceLayerCount,
nullptr));
326 vector<VkLayerProperties> instanceLayers(instanceLayerCount);
327 VK_CHECK(vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayers.data()));
329 vector<const char *> activeLayers;
330 for (
auto &ext : instanceLayers)
331 if (strcmp(ext.layerName,
"VK_LAYER_LUNARG_standard_validation") == 0)
332 activeLayers.push_back(
"VK_LAYER_LUNARG_standard_validation");
334 if (activeLayers.empty())
335 LOGI(
"Did not find validation layers.\n");
337 LOGI(
"Found validation layers!\n");
339 addExternalLayers(activeLayers, instanceLayers);
342 bool haveDebugReport =
false;
343 vector<const char *> activeInstanceExtensions;
344 for (
auto &ext : instanceExtensions)
346 if (strcmp(ext.extensionName,
"VK_EXT_debug_report") == 0)
348 haveDebugReport =
true;
349 activeInstanceExtensions.push_back(
"VK_EXT_debug_report");
354 VkApplicationInfo app = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
355 app.pApplicationName =
"Mali SDK";
356 app.applicationVersion = 0;
357 app.pEngineName =
"Mali SDK";
358 app.engineVersion = 0;
359 app.apiVersion = VK_MAKE_VERSION(1, 0, 13);
361 VkInstanceCreateInfo info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
362 info.pApplicationInfo = &app;
364 #if ENABLE_VALIDATION_LAYERS 365 if (!activeLayers.empty())
367 info.enabledLayerCount = activeLayers.size();
368 info.ppEnabledLayerNames = activeLayers.data();
369 LOGI(
"Using Vulkan instance validation layers.\n");
372 if (!activeInstanceExtensions.empty())
374 info.enabledExtensionCount = activeInstanceExtensions.size();
375 info.ppEnabledExtensionNames = activeInstanceExtensions.data();
379 VK_CHECK(vkCreateInstance(&info,
nullptr, &instance));
381 if (!vulkanSymbolWrapperLoadCoreInstanceSymbols(instance))
383 LOGE(
"Failed to load instance symbols.");
384 return RESULT_ERROR_GENERIC;
389 VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_EXTENSION_SYMBOL(instance, vkCreateDebugReportCallbackEXT);
390 VkDebugReportCallbackCreateInfoEXT info = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
391 info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT |
392 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
394 info.pfnCallback = debugCallback;
395 info.pUserData =
this;
396 if (vkCreateDebugReportCallbackEXT)
397 vkCreateDebugReportCallbackEXT(instance, &info,
nullptr, &debug_callback);
398 LOGI(
"Enabling Vulkan debug reporting.\n");
401 uint32_t gpuCount = 0;
402 VK_CHECK(vkEnumeratePhysicalDevices(instance, &gpuCount,
nullptr));
405 LOGE(
"Failed to enumerate Vulkan physical device.\n");
406 return RESULT_ERROR_GENERIC;
409 vector<VkPhysicalDevice> gpus(gpuCount);
410 VK_CHECK(vkEnumeratePhysicalDevices(instance, &gpuCount, gpus.data()));
412 gpu = VK_NULL_HANDLE;
414 for (
auto device : gpus)
416 VkPhysicalDeviceProperties properties;
417 vkGetPhysicalDeviceProperties(device, &properties);
420 if (strstr(properties.deviceName,
"Mali"))
423 LOGI(
"Found ARM Mali physical device: %s.\n", properties.deviceName);
429 if (gpu == VK_NULL_HANDLE)
432 vkGetPhysicalDeviceProperties(gpu, &gpuProperties);
433 vkGetPhysicalDeviceMemoryProperties(gpu, &memoryProperties);
436 vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queueCount,
nullptr);
437 queueProperties.resize(queueCount);
438 vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queueCount, queueProperties.data());
440 return RESULT_ERROR_GENERIC;
442 #if ENABLE_VALIDATION_LAYERS 443 uint32_t deviceLayerCount;
444 VK_CHECK(vkEnumerateDeviceLayerProperties(gpu, &deviceLayerCount,
nullptr));
445 vector<VkLayerProperties> deviceLayers(deviceLayerCount);
446 VK_CHECK(vkEnumerateDeviceLayerProperties(gpu, &deviceLayerCount, deviceLayers.data()));
448 activeLayers.clear();
449 for (
auto &ext : deviceLayers)
451 if (strcmp(ext.layerName,
"VK_LAYER_LUNARG_standard_validation") == 0)
452 activeLayers.push_back(
"VK_LAYER_LUNARG_standard_validation");
455 addExternalLayers(activeLayers, instanceLayers);
458 bool foundQueue =
false;
459 for (
unsigned i = 0; i < queueCount; i++)
461 if (queueProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
463 graphicsQueueIndex = i;
471 LOGE(
"Did not find suitable graphics queue.\n");
472 return RESULT_ERROR_GENERIC;
475 static const float one = 1.0f;
476 VkDeviceQueueCreateInfo queueInfo = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
477 queueInfo.queueFamilyIndex = graphicsQueueIndex;
478 queueInfo.queueCount = 1;
479 queueInfo.pQueuePriorities = &one;
481 VkPhysicalDeviceFeatures features = {
false };
482 VkDeviceCreateInfo deviceInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
483 deviceInfo.queueCreateInfoCount = 1;
484 deviceInfo.pQueueCreateInfos = &queueInfo;
485 deviceInfo.pEnabledFeatures = &features;
487 #if ENABLE_VALIDATION_LAYERS 488 if (!activeLayers.empty())
490 deviceInfo.enabledLayerCount = activeLayers.size();
491 deviceInfo.ppEnabledLayerNames = activeLayers.data();
492 LOGI(
"Using Vulkan device validation layers.\n");
496 VK_CHECK(vkCreateDevice(gpu, &deviceInfo,
nullptr, &device));
497 if (!vulkanSymbolWrapperLoadCoreDeviceSymbols(device))
499 LOGE(
"Failed to load device symbols.");
500 return RESULT_ERROR_GENERIC;
503 vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
505 swapchainDimensions = swapchain;
506 swapchainDimensions.
format = VK_FORMAT_R8G8B8A8_UNORM;
507 swapchainImages.resize(pngSwapchain->getNumImages());
508 swapchainMemory.resize(pngSwapchain->getNumImages());
509 swapchainReadback.resize(pngSwapchain->getNumImages());
510 swapchainReadbackMemory.resize(pngSwapchain->getNumImages());
512 for (
unsigned i = 0; i < pngSwapchain->getNumImages(); i++)
514 VkImageCreateInfo image = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
516 image.imageType = VK_IMAGE_TYPE_2D;
517 image.format = VK_FORMAT_R8G8B8A8_UNORM;
518 image.extent.width = swapchainDimensions.width;
519 image.extent.height = swapchainDimensions.height;
520 image.extent.depth = 1;
521 image.samples = VK_SAMPLE_COUNT_1_BIT;
522 image.tiling = VK_IMAGE_TILING_OPTIMAL;
523 image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
524 image.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
526 image.arrayLayers = 1;
528 VK_CHECK(vkCreateImage(device, &image,
nullptr, &swapchainImages[i]));
531 VkMemoryRequirements memReqs;
532 vkGetImageMemoryRequirements(device, swapchainImages[i], &memReqs);
534 VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
535 alloc.allocationSize = memReqs.size;
536 alloc.memoryTypeIndex =
537 findMemoryTypeFromRequirements(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
538 VK_CHECK(vkAllocateMemory(device, &alloc,
nullptr, &swapchainMemory[i]));
539 vkBindImageMemory(device, swapchainImages[i], swapchainMemory[i], 0);
542 VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
543 bufferInfo.size = swapchainDimensions.width * swapchainDimensions.height * 4;
544 bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
545 bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
547 VK_CHECK(vkCreateBuffer(device, &bufferInfo,
nullptr, &swapchainReadback[i]));
548 vkGetBufferMemoryRequirements(device, swapchainReadback[i], &memReqs);
550 alloc.allocationSize = memReqs.size;
553 alloc.memoryTypeIndex = findMemoryTypeFromRequirementsFallback(
554 memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
555 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
556 VK_CHECK(vkAllocateMemory(device, &alloc,
nullptr, &swapchainReadbackMemory[i]));
561 swapchainCoherent = (memoryProperties.memoryTypes[alloc.memoryTypeIndex].propertyFlags &
562 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
564 vkBindBufferMemory(device, swapchainReadback[i], swapchainReadbackMemory[i], 0);
567 Result res = pContext->onPlatformUpdate(
this);
569 return RESULT_ERROR_GENERIC;
571 return RESULT_SUCCESS;
The Context is the primary way for samples to interact with the swapchain and get rendered images to ...
This class implements a swapchain outside the Vulkan API. Its main purpose is debugging without a scr...