/*
- * Copyright (c) 2015-2016 The Khronos Group Inc.
- * Copyright (c) 2015-2016 Valve Corporation
- * Copyright (c) 2015-2016 LunarG, Inc.
+ * Copyright (c) 2015-2019 The Khronos Group Inc.
+ * Copyright (c) 2015-2019 Valve Corporation
+ * Copyright (c) 2015-2019 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
void DbgMsg(char *fmt, ...) {
va_list va;
va_start(va, fmt);
- printf(fmt, va);
- fflush(stdout);
+ vprintf(fmt, va);
va_end(va);
+ fflush(stdout);
}
#elif defined __ANDROID__
#include <android/log.h>
-#define ERR_EXIT(err_msg, err_class) \
- do { \
+#define ERR_EXIT(err_msg, err_class) \
+ do { \
((void)__android_log_print(ANDROID_LOG_INFO, "Vulkan Cube", err_msg)); \
- exit(1); \
+ exit(1); \
} while (0)
#ifdef VARARGS_WORKS_ON_ANDROID
void DbgMsg(const char *fmt, ...) {
va_end(va);
}
#else // VARARGS_WORKS_ON_ANDROID
-#define DbgMsg(fmt, ...) \
- do { \
+#define DbgMsg(fmt, ...) \
+ do { \
((void)__android_log_print(ANDROID_LOG_INFO, "Vulkan Cube", fmt, ##__VA_ARGS__)); \
} while (0)
#endif // VARARGS_WORKS_ON_ANDROID
void DbgMsg(char *fmt, ...) {
va_list va;
va_start(va, fmt);
- printf(fmt, va);
- fflush(stdout);
+ vprintf(fmt, va);
va_end(va);
+ fflush(stdout);
}
#endif
VkImageView view;
VkBuffer uniform_buffer;
VkDeviceMemory uniform_memory;
+ void *uniform_memory_ptr;
VkFramebuffer framebuffer;
VkDescriptorSet descriptor_set;
} SwapchainImageResources;
struct wl_keyboard *keyboard;
#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
struct ANativeWindow *window;
-#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
- void *window;
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
+ void *caMetalLayer;
#endif
VkSurfaceKHR surface;
bool prepared;
#ifdef _WIN32
in_callback = true;
- if (!demo->suppress_popups)
- MessageBox(NULL, message, "Alert", MB_OK);
+ if (!demo->suppress_popups) MessageBox(NULL, message, "Alert", MB_OK);
in_callback = false;
#elif defined(ANDROID)
if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
- __android_log_print(ANDROID_LOG_INFO, APP_SHORT_NAME, "%s", message);
+ __android_log_print(ANDROID_LOG_INFO, APP_SHORT_NAME, "%s", message);
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
- __android_log_print(ANDROID_LOG_WARN, APP_SHORT_NAME, "%s", message);
+ __android_log_print(ANDROID_LOG_WARN, APP_SHORT_NAME, "%s", message);
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
__android_log_print(ANDROID_LOG_ERROR, APP_SHORT_NAME, "%s", message);
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
__android_log_print(ANDROID_LOG_VERBOSE, APP_SHORT_NAME, "%s", message);
} else {
- __android_log_print(ANDROID_LOG_INFO, APP_SHORT_NAME, "%s", message);
+ __android_log_print(ANDROID_LOG_INFO, APP_SHORT_NAME, "%s", message);
}
#else
return false;
}
-// Forward declaration:
+// Forward declarations:
static void demo_resize(struct demo *demo);
+static void demo_create_surface(struct demo *demo);
static bool memory_type_from_properties(struct demo *demo, uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex) {
// Search memtypes to find first index with those properties
&demo->swapchain_image_resources[demo->current_buffer].descriptor_set, 0, NULL);
VkViewport viewport;
memset(&viewport, 0, sizeof(viewport));
- viewport.height = (float)demo->height;
- viewport.width = (float)demo->width;
+ float viewport_dimension;
+ if (demo->width < demo->height) {
+ viewport_dimension = (float)demo->width;
+ viewport.y = (demo->height - demo->width) / 2.0f;
+ } else {
+ viewport_dimension = (float)demo->height;
+ viewport.x = (demo->width - demo->height) / 2.0f;
+ }
+ viewport.height = viewport_dimension;
+ viewport.width = viewport_dimension;
viewport.minDepth = (float)0.0f;
viewport.maxDepth = (float)1.0f;
vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
void demo_update_data_buffer(struct demo *demo) {
mat4x4 MVP, Model, VP;
int matrixSize = sizeof(MVP);
- uint8_t *pData;
- VkResult U_ASSERT_ONLY err;
mat4x4_mul(VP, demo->projection_matrix, demo->view_matrix);
mat4x4_rotate(demo->model_matrix, Model, 0.0f, 1.0f, 0.0f, (float)degreesToRadians(demo->spin_angle));
mat4x4_mul(MVP, VP, demo->model_matrix);
- err = vkMapMemory(demo->device, demo->swapchain_image_resources[demo->current_buffer].uniform_memory, 0, VK_WHOLE_SIZE, 0,
- (void **)&pData);
- assert(!err);
-
- memcpy(pData, (const void *)&MVP[0][0], matrixSize);
-
- vkUnmapMemory(demo->device, demo->swapchain_image_resources[demo->current_buffer].uniform_memory);
+ memcpy(demo->swapchain_image_resources[demo->current_buffer].uniform_memory_ptr, (const void *)&MVP[0][0], matrixSize);
}
void DemoUpdateTargetIPD(struct demo *demo) {
// demo->swapchain is not as optimal as it could be, but the platform's
// presentation engine will still present the image correctly.
break;
+ } else if (err == VK_ERROR_SURFACE_LOST_KHR) {
+ vkDestroySurfaceKHR(demo->inst, demo->surface, NULL);
+ demo_create_surface(demo);
+ demo_resize(demo);
} else {
assert(!err);
}
} else if (err == VK_SUBOPTIMAL_KHR) {
// demo->swapchain is not as optimal as it could be, but the platform's
// presentation engine will still present the image correctly.
+ } else if (err == VK_ERROR_SURFACE_LOST_KHR) {
+ vkDestroySurfaceKHR(demo->inst, demo->surface, NULL);
+ demo_create_surface(demo);
+ demo_resize(demo);
} else {
assert(!err);
}
demo->next_present_id = 1;
}
+ if (NULL != swapchainImages) {
+ free(swapchainImages);
+ }
+
if (NULL != presentModes) {
free(presentModes);
}
VkBufferCreateInfo buf_info;
VkMemoryRequirements mem_reqs;
VkMemoryAllocateInfo mem_alloc;
- uint8_t *pData;
mat4x4 MVP, VP;
VkResult U_ASSERT_ONLY err;
bool U_ASSERT_ONLY pass;
err = vkAllocateMemory(demo->device, &mem_alloc, NULL, &demo->swapchain_image_resources[i].uniform_memory);
assert(!err);
- err = vkMapMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory, 0, VK_WHOLE_SIZE, 0, (void **)&pData);
+ err = vkMapMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory, 0, VK_WHOLE_SIZE, 0,
+ &demo->swapchain_image_resources[i].uniform_memory_ptr);
assert(!err);
- memcpy(pData, &data, sizeof data);
-
- vkUnmapMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory);
+ memcpy(demo->swapchain_image_resources[i].uniform_memory_ptr, &data, sizeof data);
err = vkBindBufferMemory(demo->device, demo->swapchain_image_resources[i].uniform_buffer,
demo->swapchain_image_resources[i].uniform_memory, 0);
.preserveAttachmentCount = 0,
.pPreserveAttachments = NULL,
};
+
+ VkSubpassDependency attachmentDependencies[2] = {
+ [0] =
+ {
+ // Depth buffer is shared between swapchain images
+ .srcSubpass = VK_SUBPASS_EXTERNAL,
+ .dstSubpass = 0,
+ .srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+ .dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+ .srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ .dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ .dependencyFlags = 0,
+ },
+ [1] =
+ {
+ // Image Layout Transition
+ .srcSubpass = VK_SUBPASS_EXTERNAL,
+ .dstSubpass = 0,
+ .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ .srcAccessMask = 0,
+ .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
+ .dependencyFlags = 0,
+ },
+ };
+
const VkRenderPassCreateInfo rp_info = {
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
.pNext = NULL,
.pAttachments = attachments,
.subpassCount = 1,
.pSubpasses = &subpass,
- .dependencyCount = 0,
- .pDependencies = NULL,
+ .dependencyCount = 2,
+ .pDependencies = attachmentDependencies,
};
VkResult U_ASSERT_ONLY err;
vkDestroyImageView(demo->device, demo->swapchain_image_resources[i].view, NULL);
vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->swapchain_image_resources[i].cmd);
vkDestroyBuffer(demo->device, demo->swapchain_image_resources[i].uniform_buffer, NULL);
+ vkUnmapMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory);
vkFreeMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory, NULL);
}
free(demo->swapchain_image_resources);
vkDestroyImageView(demo->device, demo->swapchain_image_resources[i].view, NULL);
vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->swapchain_image_resources[i].cmd);
vkDestroyBuffer(demo->device, demo->swapchain_image_resources[i].uniform_buffer, NULL);
+ vkUnmapMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory);
vkFreeMemory(demo->device, demo->swapchain_image_resources[i].uniform_memory, NULL);
}
vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL);
demo_draw(demo);
demo->curFrame++;
}
-#elif defined(VK_USE_PLATFORM_MACOS_MVK)
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
static void demo_run(struct demo *demo) {
demo_draw(demo);
demo->curFrame++;
platformSurfaceExtFound = 1;
demo->extension_names[demo->enabled_extension_count++] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
}
-#elif defined(VK_USE_PLATFORM_IOS_MVK)
- if (!strcmp(VK_MVK_IOS_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) {
- platformSurfaceExtFound = 1;
- demo->extension_names[demo->enabled_extension_count++] = VK_MVK_IOS_SURFACE_EXTENSION_NAME;
- }
-#elif defined(VK_USE_PLATFORM_MACOS_MVK)
- if (!strcmp(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) {
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
+ if (!strcmp(VK_EXT_METAL_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) {
platformSurfaceExtFound = 1;
- demo->extension_names[demo->enabled_extension_count++] = VK_MVK_MACOS_SURFACE_EXTENSION_NAME;
+ demo->extension_names[demo->enabled_extension_count++] = VK_EXT_METAL_SURFACE_EXTENSION_NAME;
}
#endif
if (!strcmp(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instance_extensions[i].extensionName)) {
"Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
"Please look at the Getting Started guide for additional information.\n",
"vkCreateInstance Failure");
-#elif defined(VK_USE_PLATFORM_IOS_MVK)
- ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find the " VK_MVK_IOS_SURFACE_EXTENSION_NAME
- " extension.\n\n"
- "Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
- "Please look at the Getting Started guide for additional information.\n",
- "vkCreateInstance Failure");
-#elif defined(VK_USE_PLATFORM_MACOS_MVK)
- ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find the " VK_MVK_MACOS_SURFACE_EXTENSION_NAME
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
+ ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find the " VK_EXT_METAL_SURFACE_EXTENSION_NAME
" extension.\n\n"
"Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
"Please look at the Getting Started guide for additional information.\n",
assert(!err);
}
-static void demo_init_vk_swapchain(struct demo *demo) {
+static void demo_create_surface(struct demo *demo) {
VkResult U_ASSERT_ONLY err;
// Create a WSI surface for the window:
err = vkCreateXcbSurfaceKHR(demo->inst, &createInfo, NULL, &demo->surface);
#elif defined(VK_USE_PLATFORM_DISPLAY_KHR)
err = demo_create_display_surface(demo);
-#elif defined(VK_USE_PLATFORM_IOS_MVK)
- VkIOSSurfaceCreateInfoMVK surface;
- surface.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
- surface.pNext = NULL;
- surface.flags = 0;
- surface.pView = demo->window;
-
- err = vkCreateIOSSurfaceMVK(demo->inst, &surface, NULL, &demo->surface);
-#elif defined(VK_USE_PLATFORM_MACOS_MVK)
- VkMacOSSurfaceCreateInfoMVK surface;
- surface.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
+ VkMetalSurfaceCreateInfoEXT surface;
+ surface.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
surface.pNext = NULL;
surface.flags = 0;
- surface.pView = demo->window;
+ surface.pLayer = demo->caMetalLayer;
- err = vkCreateMacOSSurfaceMVK(demo->inst, &surface, NULL, &demo->surface);
+ err = vkCreateMetalSurfaceEXT(demo->inst, &surface, NULL, &demo->surface);
#endif
assert(!err);
+}
+
+static void demo_init_vk_swapchain(struct demo *demo) {
+ VkResult U_ASSERT_ONLY err;
+
+ demo_create_surface(demo);
// Iterate over each queue to learn whether it supports presenting:
VkBool32 *supportsPresent = (VkBool32 *)malloc(demo->queue_family_count * sizeof(VkBool32));
VkSurfaceFormatKHR *surfFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
err = demo->fpGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface, &formatCount, surfFormats);
assert(!err);
- // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
- // the surface has no preferred format. Otherwise, at least one
- // supported format will be returned.
- if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED) {
- demo->format = VK_FORMAT_B8G8R8A8_UNORM;
- } else {
- assert(formatCount >= 1);
- demo->format = surfFormats[0].format;
- }
+ assert(formatCount >= 1);
+ demo->format = surfFormats[0].format;
demo->color_space = surfFormats[0].colorSpace;
+ free(surfFormats);
demo->quit = false;
demo->curFrame = 0;
seat_handle_capabilities,
};
-static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface,
- uint32_t version UNUSED) {
+static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) {
struct demo *demo = data;
// pickup wayland objects when they appear
if (strcmp(interface, "wl_compositor") == 0) {
- demo->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1);
+ uint32_t minVersion = version < 4 ? version : 4;
+ demo->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, minVersion);
+ if (demo->VK_KHR_incremental_present_enabled && minVersion < 4) {
+ fprintf(stderr, "Wayland compositor doesn't support VK_KHR_incremental_present, disabling.\n");
+ demo->VK_KHR_incremental_present_enabled = false;
+ }
} else if (strcmp(interface, "wl_shell") == 0) {
demo->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1);
} else if (strcmp(interface, "wl_seat") == 0) {
#if defined(ANDROID)
ERR_EXIT("Usage: vkcube [--validate]\n", "Usage");
#else
- fprintf(stderr,
- "Usage:\n %s\t[--use_staging] [--validate] [--validate-checks-disabled] [--break]\n"
- "\t[--c <framecount>] [--suppress_popups] [--incremental_present] [--display_timing]\n"
- "\t[--present_mode <present mode enum>]\n"
- "\t <present_mode_enum>\tVK_PRESENT_MODE_IMMEDIATE_KHR = %d\n"
- "\t\t\t\tVK_PRESENT_MODE_MAILBOX_KHR = %d\n"
- "\t\t\t\tVK_PRESENT_MODE_FIFO_KHR = %d\n"
- "\t\t\t\tVK_PRESENT_MODE_FIFO_RELAXED_KHR = %d\n",
- APP_SHORT_NAME, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR,
- VK_PRESENT_MODE_FIFO_RELAXED_KHR);
+ char *message =
+ "Usage:\n %s\t[--use_staging] [--validate] [--validate-checks-disabled]\n"
+ "\t[--break] [--c <framecount>] [--suppress_popups]\n"
+ "\t[--incremental_present] [--display_timing]\n"
+ "\t[--present_mode <present mode enum>]\n"
+ "\t<present_mode_enum>\n"
+ "\t\tVK_PRESENT_MODE_IMMEDIATE_KHR = %d\n"
+ "\t\tVK_PRESENT_MODE_MAILBOX_KHR = %d\n"
+ "\t\tVK_PRESENT_MODE_FIFO_KHR = %d\n"
+ "\t\tVK_PRESENT_MODE_FIFO_RELAXED_KHR = %d\n";
+ int length = snprintf(NULL, 0, message, APP_SHORT_NAME, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR,
+ VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR);
+ char *usage = (char *)malloc(length + 1);
+ if (!usage) {
+ exit(1);
+ }
+ snprintf(usage, length + 1, message, APP_SHORT_NAME, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR,
+ VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR);
+#if defined(_WIN32)
+ if (!demo->suppress_popups) MessageBox(NULL, usage, "Usage Error", MB_OK);
+#else
+ fprintf(stderr, "%s", usage);
fflush(stderr);
+#endif
+ free(usage);
exit(1);
#endif
}
return (int)msg.wParam;
}
-#elif defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK)
-static void demo_main(struct demo *demo, void *view, int argc, const char *argv[]) {
-
+#elif defined(VK_USE_PLATFORM_METAL_EXT)
+static void demo_main(struct demo *demo, void *caMetalLayer, int argc, const char *argv[]) {
demo_init(demo, argc, (char **)argv);
- demo->window = view;
+ demo->caMetalLayer = caMetalLayer;
demo_init_vk_swapchain(demo);
demo_prepare(demo);
demo->spin_angle = 0.4f;