2 #define _ISOC11_SOURCE /* for aligned_alloc() */
14 #include <vulkan/vulkan.h>
17 #define DEMO_TEXTURE_COUNT 1
18 #define VERTEX_BUFFER_BIND_ID 0
19 #define APP_SHORT_NAME "tri"
20 #define APP_LONG_NAME "The Vulkan Triangle Demo Program"
22 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
24 #if defined(NDEBUG) && defined(__GNUC__)
25 #define U_ASSERT_ONLY __attribute__((unused))
30 #define ERR_EXIT(err_msg, err_class) \
37 #define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
39 demo->fp##entrypoint = \
40 (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \
41 if (demo->fp##entrypoint == NULL) { \
42 ERR_EXIT("vkGetInstanceProcAddr failed to find vk" #entrypoint, \
43 "vkGetInstanceProcAddr Failure"); \
47 #define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
49 demo->fp##entrypoint = \
50 (PFN_vk##entrypoint)vkGetDeviceProcAddr(dev, "vk" #entrypoint); \
51 if (demo->fp##entrypoint == NULL) { \
52 ERR_EXIT("vkGetDeviceProcAddr failed to find vk" #entrypoint, \
53 "vkGetDeviceProcAddr Failure"); \
57 struct texture_object {
61 VkImageLayout imageLayout;
65 int32_t tex_width, tex_height;
68 static int validation_error = 0;
70 VKAPI_ATTR VkBool32 VKAPI_CALL
71 dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
72 uint64_t srcObject, size_t location, int32_t msgCode,
73 const char *pLayerPrefix, const char *pMsg, void *pUserData) {
74 char *message = (char *)malloc(strlen(pMsg) + 100);
80 if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
81 sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode,
83 } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
84 sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode,
90 printf("%s\n", message);
95 * false indicates that layer should not bail-out of an
96 * API call that had validation failures. This may mean that the
97 * app dies inside the driver due to invalid parameter(s).
98 * That's what would happen without validation layers, so we'll
99 * keep that behavior here.
104 VKAPI_ATTR VkBool32 VKAPI_CALL
105 BreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
106 uint64_t srcObject, size_t location, int32_t msgCode,
107 const char *pLayerPrefix, const char *pMsg,
113 typedef struct _SwapchainBuffers {
120 SDL_Window* sdl_window;
121 SDL_DisplayMode sdl_mode;
123 VkSurfaceKHR surface;
125 bool use_staging_buffer;
128 VkPhysicalDevice gpu;
131 VkPhysicalDeviceProperties gpu_props;
132 VkQueueFamilyProperties *queue_props;
133 uint32_t graphics_queue_node_index;
135 uint32_t enabled_extension_count;
136 uint32_t enabled_layer_count;
137 char *extension_names[64];
138 char *device_validation_layers[64];
142 VkColorSpaceKHR color_space;
144 PFN_vkGetPhysicalDeviceSurfaceSupportKHR
145 fpGetPhysicalDeviceSurfaceSupportKHR;
146 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
147 fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
148 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR
149 fpGetPhysicalDeviceSurfaceFormatsKHR;
150 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR
151 fpGetPhysicalDeviceSurfacePresentModesKHR;
152 PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR;
153 PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR;
154 PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR;
155 PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR;
156 PFN_vkQueuePresentKHR fpQueuePresentKHR;
157 uint32_t swapchainImageCount;
158 VkSwapchainKHR swapchain;
159 SwapchainBuffers *buffers;
161 VkCommandPool cmd_pool;
171 struct texture_object textures[DEMO_TEXTURE_COUNT];
177 VkPipelineVertexInputStateCreateInfo vi;
178 VkVertexInputBindingDescription vi_bindings[1];
179 VkVertexInputAttributeDescription vi_attrs[2];
182 VkCommandBuffer setup_cmd; // Command Buffer for initialization commands
183 VkCommandBuffer draw_cmd; // Command Buffer for drawing commands
184 VkPipelineLayout pipeline_layout;
185 VkDescriptorSetLayout desc_layout;
186 VkPipelineCache pipelineCache;
187 VkRenderPass render_pass;
190 VkShaderModule vert_shader_module;
191 VkShaderModule frag_shader_module;
193 VkDescriptorPool desc_pool;
194 VkDescriptorSet desc_set;
196 VkFramebuffer *framebuffers;
198 VkPhysicalDeviceMemoryProperties memory_properties;
204 PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback;
205 PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback;
206 VkDebugReportCallbackEXT msg_callback;
207 PFN_vkDebugReportMessageEXT DebugReportMessage;
210 float depthIncrement;
213 uint32_t current_buffer;
214 uint32_t queue_count;
217 // Forward declaration:
218 static void demo_resize(struct demo *demo);
220 static bool memory_type_from_properties(struct demo *demo, uint32_t typeBits,
221 VkFlags requirements_mask,
222 uint32_t *typeIndex) {
225 // Search memtypes to find first index with those properties
226 for (i = 0; i < 32; i++) {
227 if ((typeBits & 1) == 1) {
228 // Type is available, does it match user properties?
229 if ((demo->memory_properties.memoryTypes[i].propertyFlags &
230 requirements_mask) == requirements_mask) {
237 // No memory types matched, return failure
241 static void demo_flush_init_cmd(struct demo *demo) {
242 VkResult U_ASSERT_ONLY err;
244 if (demo->setup_cmd == VK_NULL_HANDLE)
247 err = vkEndCommandBuffer(demo->setup_cmd);
250 const VkCommandBuffer cmd_bufs[] = {demo->setup_cmd};
251 VkFence nullFence = {VK_NULL_HANDLE};
252 VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
254 .waitSemaphoreCount = 0,
255 .pWaitSemaphores = NULL,
256 .pWaitDstStageMask = NULL,
257 .commandBufferCount = 1,
258 .pCommandBuffers = cmd_bufs,
259 .signalSemaphoreCount = 0,
260 .pSignalSemaphores = NULL};
262 err = vkQueueSubmit(demo->queue, 1, &submit_info, nullFence);
265 err = vkQueueWaitIdle(demo->queue);
268 vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, cmd_bufs);
269 demo->setup_cmd = VK_NULL_HANDLE;
272 static void demo_set_image_layout(struct demo *demo, VkImage image,
273 VkImageAspectFlags aspectMask,
274 VkImageLayout old_image_layout,
275 VkImageLayout new_image_layout,
276 VkAccessFlagBits srcAccessMask) {
278 VkResult U_ASSERT_ONLY err;
280 if (demo->setup_cmd == VK_NULL_HANDLE) {
281 const VkCommandBufferAllocateInfo cmd = {
282 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
284 .commandPool = demo->cmd_pool,
285 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
286 .commandBufferCount = 1,
289 err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->setup_cmd);
292 VkCommandBufferInheritanceInfo cmd_buf_hinfo = {
293 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
295 .renderPass = VK_NULL_HANDLE,
297 .framebuffer = VK_NULL_HANDLE,
298 .occlusionQueryEnable = VK_FALSE,
300 .pipelineStatistics = 0,
302 VkCommandBufferBeginInfo cmd_buf_info = {
303 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
306 .pInheritanceInfo = &cmd_buf_hinfo,
308 err = vkBeginCommandBuffer(demo->setup_cmd, &cmd_buf_info);
312 VkImageMemoryBarrier image_memory_barrier = {
313 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
315 .srcAccessMask = srcAccessMask,
317 .oldLayout = old_image_layout,
318 .newLayout = new_image_layout,
320 .subresourceRange = {aspectMask, 0, 1, 0, 1}};
322 if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
323 /* Make sure anything that was copying from this image has completed */
324 image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
327 if (new_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
328 image_memory_barrier.dstAccessMask =
329 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
332 if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
333 image_memory_barrier.dstAccessMask =
334 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
337 if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
338 /* Make sure any Copy or CPU writes to image are flushed */
339 image_memory_barrier.dstAccessMask =
340 VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
343 VkImageMemoryBarrier *pmemory_barrier = &image_memory_barrier;
345 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
346 VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
348 vkCmdPipelineBarrier(demo->setup_cmd, src_stages, dest_stages, 0, 0, NULL,
349 0, NULL, 1, pmemory_barrier);
352 static void demo_draw_build_cmd(struct demo *demo) {
353 const VkCommandBufferInheritanceInfo cmd_buf_hinfo = {
354 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
356 .renderPass = VK_NULL_HANDLE,
358 .framebuffer = VK_NULL_HANDLE,
359 .occlusionQueryEnable = VK_FALSE,
361 .pipelineStatistics = 0,
363 const VkCommandBufferBeginInfo cmd_buf_info = {
364 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
367 .pInheritanceInfo = &cmd_buf_hinfo,
369 const VkClearValue clear_values[2] = {
370 [0] = {.color.float32 = {0.2f, 0.2f, 0.2f, 0.2f}},
371 [1] = {.depthStencil = {demo->depthStencil, 0}},
373 const VkRenderPassBeginInfo rp_begin = {
374 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
376 .renderPass = demo->render_pass,
377 .framebuffer = demo->framebuffers[demo->current_buffer],
378 .renderArea.offset.x = 0,
379 .renderArea.offset.y = 0,
380 .renderArea.extent.width = demo->width,
381 .renderArea.extent.height = demo->height,
382 .clearValueCount = 2,
383 .pClearValues = clear_values,
385 VkResult U_ASSERT_ONLY err;
387 err = vkBeginCommandBuffer(demo->draw_cmd, &cmd_buf_info);
390 vkCmdBeginRenderPass(demo->draw_cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);
391 vkCmdBindPipeline(demo->draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
393 vkCmdBindDescriptorSets(demo->draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
394 demo->pipeline_layout, 0, 1, &demo->desc_set, 0,
398 memset(&viewport, 0, sizeof(viewport));
399 viewport.height = (float)demo->height;
400 viewport.width = (float)demo->width;
401 viewport.minDepth = (float)0.0f;
402 viewport.maxDepth = (float)1.0f;
403 vkCmdSetViewport(demo->draw_cmd, 0, 1, &viewport);
406 memset(&scissor, 0, sizeof(scissor));
407 scissor.extent.width = demo->width;
408 scissor.extent.height = demo->height;
409 scissor.offset.x = 0;
410 scissor.offset.y = 0;
411 vkCmdSetScissor(demo->draw_cmd, 0, 1, &scissor);
413 VkDeviceSize offsets[1] = {0};
414 vkCmdBindVertexBuffers(demo->draw_cmd, VERTEX_BUFFER_BIND_ID, 1,
415 &demo->vertices.buf, offsets);
417 vkCmdDraw(demo->draw_cmd, 3, 1, 0, 0);
418 vkCmdEndRenderPass(demo->draw_cmd);
420 VkImageMemoryBarrier prePresentBarrier = {
421 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
423 .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
424 .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
425 .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
426 .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
427 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
428 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
429 .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}};
431 prePresentBarrier.image = demo->buffers[demo->current_buffer].image;
432 VkImageMemoryBarrier *pmemory_barrier = &prePresentBarrier;
433 vkCmdPipelineBarrier(demo->draw_cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
434 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0,
435 NULL, 1, pmemory_barrier);
437 err = vkEndCommandBuffer(demo->draw_cmd);
441 static void demo_draw(struct demo *demo) {
442 VkResult U_ASSERT_ONLY err;
443 VkSemaphore presentCompleteSemaphore;
444 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {
445 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
450 err = vkCreateSemaphore(demo->device, &presentCompleteSemaphoreCreateInfo,
451 NULL, &presentCompleteSemaphore);
454 // Get the index of the next available swapchain image:
455 err = demo->fpAcquireNextImageKHR(demo->device, demo->swapchain, UINT64_MAX,
456 presentCompleteSemaphore,
457 (VkFence)0, // TODO: Show use of fence
458 &demo->current_buffer);
459 if (err == VK_ERROR_OUT_OF_DATE_KHR) {
460 // demo->swapchain is out of date (e.g. the window was resized) and
461 // must be recreated:
464 vkDestroySemaphore(demo->device, presentCompleteSemaphore, NULL);
466 } else if (err == VK_SUBOPTIMAL_KHR) {
467 // demo->swapchain is not as optimal as it could be, but the platform's
468 // presentation engine will still present the image correctly.
473 // Assume the command buffer has been run on current_buffer before so
474 // we need to set the image layout back to COLOR_ATTACHMENT_OPTIMAL
475 demo_set_image_layout(demo, demo->buffers[demo->current_buffer].image,
476 VK_IMAGE_ASPECT_COLOR_BIT,
477 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
478 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
480 demo_flush_init_cmd(demo);
482 // Wait for the present complete semaphore to be signaled to ensure
483 // that the image won't be rendered to until the presentation
484 // engine has fully released ownership to the application, and it is
485 // okay to render to the image.
487 // FIXME/TODO: DEAL WITH VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
488 demo_draw_build_cmd(demo);
489 VkFence nullFence = VK_NULL_HANDLE;
490 VkPipelineStageFlags pipe_stage_flags =
491 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
492 VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
494 .waitSemaphoreCount = 0,
495 .pWaitSemaphores = &presentCompleteSemaphore,
496 .pWaitDstStageMask = &pipe_stage_flags,
497 .commandBufferCount = 1,
498 .pCommandBuffers = &demo->draw_cmd,
499 .signalSemaphoreCount = 0,
500 .pSignalSemaphores = NULL};
502 err = vkQueueSubmit(demo->queue, 1, &submit_info, nullFence);
505 VkPresentInfoKHR present = {
506 .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
509 .pSwapchains = &demo->swapchain,
510 .pImageIndices = &demo->current_buffer,
513 // TBD/TODO: SHOULD THE "present" PARAMETER BE "const" IN THE HEADER?
514 err = demo->fpQueuePresentKHR(demo->queue, &present);
515 if (err == VK_ERROR_OUT_OF_DATE_KHR) {
516 // demo->swapchain is out of date (e.g. the window was resized) and
517 // must be recreated:
519 } else if (err == VK_SUBOPTIMAL_KHR) {
520 // demo->swapchain is not as optimal as it could be, but the platform's
521 // presentation engine will still present the image correctly.
526 err = vkQueueWaitIdle(demo->queue);
527 assert(err == VK_SUCCESS);
529 vkDestroySemaphore(demo->device, presentCompleteSemaphore, NULL);
532 static void demo_prepare_buffers(struct demo *demo) {
533 VkResult U_ASSERT_ONLY err;
534 VkSwapchainKHR oldSwapchain = demo->swapchain;
536 // Check the surface capabilities and formats
537 VkSurfaceCapabilitiesKHR surfCapabilities;
538 err = demo->fpGetPhysicalDeviceSurfaceCapabilitiesKHR(
539 demo->gpu, demo->surface, &surfCapabilities);
542 uint32_t presentModeCount;
543 err = demo->fpGetPhysicalDeviceSurfacePresentModesKHR(
544 demo->gpu, demo->surface, &presentModeCount, NULL);
546 VkPresentModeKHR *presentModes =
547 (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
548 assert(presentModes);
549 err = demo->fpGetPhysicalDeviceSurfacePresentModesKHR(
550 demo->gpu, demo->surface, &presentModeCount, presentModes);
553 VkExtent2D swapchainExtent;
554 // width and height are either both -1, or both not -1.
555 if (surfCapabilities.currentExtent.width == (uint32_t)-1) {
556 // If the surface size is undefined, the size is set to
557 // the size of the images requested.
558 swapchainExtent.width = demo->width;
559 swapchainExtent.height = demo->height;
561 // If the surface size is defined, the swap chain size must match
562 swapchainExtent = surfCapabilities.currentExtent;
563 demo->width = surfCapabilities.currentExtent.width;
564 demo->height = surfCapabilities.currentExtent.height;
567 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
569 // Determine the number of VkImage's to use in the swap chain (we desire to
570 // own only 1 image at a time, besides the images being displayed and
571 // queued for display):
572 uint32_t desiredNumberOfSwapchainImages =
573 surfCapabilities.minImageCount + 1;
574 if ((surfCapabilities.maxImageCount > 0) &&
575 (desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount)) {
576 // Application must settle for fewer images than desired:
577 desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount;
580 VkSurfaceTransformFlagsKHR preTransform;
581 if (surfCapabilities.supportedTransforms &
582 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
583 preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
585 preTransform = surfCapabilities.currentTransform;
588 const VkSwapchainCreateInfoKHR swapchain = {
589 .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
591 .surface = demo->surface,
592 .minImageCount = desiredNumberOfSwapchainImages,
593 .imageFormat = demo->format,
594 .imageColorSpace = demo->color_space,
597 .width = swapchainExtent.width, .height = swapchainExtent.height,
599 .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
600 .preTransform = preTransform,
601 .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
602 .imageArrayLayers = 1,
603 .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
604 .queueFamilyIndexCount = 0,
605 .pQueueFamilyIndices = NULL,
606 .presentMode = swapchainPresentMode,
607 .oldSwapchain = oldSwapchain,
612 err = demo->fpCreateSwapchainKHR(demo->device, &swapchain, NULL,
616 // If we just re-created an existing swapchain, we should destroy the old
617 // swapchain at this point.
618 // Note: destroying the swapchain also cleans up all its associated
619 // presentable images once the platform is done with them.
620 if (oldSwapchain != VK_NULL_HANDLE) {
621 demo->fpDestroySwapchainKHR(demo->device, oldSwapchain, NULL);
624 err = demo->fpGetSwapchainImagesKHR(demo->device, demo->swapchain,
625 &demo->swapchainImageCount, NULL);
628 VkImage *swapchainImages =
629 (VkImage *)malloc(demo->swapchainImageCount * sizeof(VkImage));
630 assert(swapchainImages);
631 err = demo->fpGetSwapchainImagesKHR(demo->device, demo->swapchain,
632 &demo->swapchainImageCount,
636 demo->buffers = (SwapchainBuffers *)malloc(sizeof(SwapchainBuffers) *
637 demo->swapchainImageCount);
638 assert(demo->buffers);
640 for (i = 0; i < demo->swapchainImageCount; i++) {
641 VkImageViewCreateInfo color_attachment_view = {
642 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
644 .format = demo->format,
647 .r = VK_COMPONENT_SWIZZLE_R,
648 .g = VK_COMPONENT_SWIZZLE_G,
649 .b = VK_COMPONENT_SWIZZLE_B,
650 .a = VK_COMPONENT_SWIZZLE_A,
652 .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
657 .viewType = VK_IMAGE_VIEW_TYPE_2D,
661 demo->buffers[i].image = swapchainImages[i];
663 // Render loop will expect image to have been used before and in
664 // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
665 // layout and will change to COLOR_ATTACHMENT_OPTIMAL, so init the image
667 demo_set_image_layout(
668 demo, demo->buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
669 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
672 color_attachment_view.image = demo->buffers[i].image;
674 err = vkCreateImageView(demo->device, &color_attachment_view, NULL,
675 &demo->buffers[i].view);
679 demo->current_buffer = 0;
681 if (NULL != presentModes) {
686 static void demo_prepare_depth(struct demo *demo) {
687 const VkFormat depth_format = VK_FORMAT_D16_UNORM;
688 const VkImageCreateInfo image = {
689 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
691 .imageType = VK_IMAGE_TYPE_2D,
692 .format = depth_format,
693 .extent = {demo->width, demo->height, 1},
696 .samples = VK_SAMPLE_COUNT_1_BIT,
697 .tiling = VK_IMAGE_TILING_OPTIMAL,
698 .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
701 VkMemoryAllocateInfo mem_alloc = {
702 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
705 .memoryTypeIndex = 0,
707 VkImageViewCreateInfo view = {
708 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
710 .image = VK_NULL_HANDLE,
711 .format = depth_format,
712 .subresourceRange = {.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
718 .viewType = VK_IMAGE_VIEW_TYPE_2D,
721 VkMemoryRequirements mem_reqs;
722 VkResult U_ASSERT_ONLY err;
723 bool U_ASSERT_ONLY pass;
725 demo->depth.format = depth_format;
728 err = vkCreateImage(demo->device, &image, NULL, &demo->depth.image);
731 /* get memory requirements for this object */
732 vkGetImageMemoryRequirements(demo->device, demo->depth.image, &mem_reqs);
734 /* select memory size and type */
735 mem_alloc.allocationSize = mem_reqs.size;
736 pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
737 0, /* No requirements */
738 &mem_alloc.memoryTypeIndex);
741 /* allocate memory */
742 err = vkAllocateMemory(demo->device, &mem_alloc, NULL, &demo->depth.mem);
747 vkBindImageMemory(demo->device, demo->depth.image, demo->depth.mem, 0);
750 demo_set_image_layout(demo, demo->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT,
751 VK_IMAGE_LAYOUT_UNDEFINED,
752 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
755 /* create image view */
756 view.image = demo->depth.image;
757 err = vkCreateImageView(demo->device, &view, NULL, &demo->depth.view);
762 demo_prepare_texture_image(struct demo *demo, const uint32_t *tex_colors,
763 struct texture_object *tex_obj, VkImageTiling tiling,
764 VkImageUsageFlags usage, VkFlags required_props) {
765 const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
766 const int32_t tex_width = 2;
767 const int32_t tex_height = 2;
768 VkResult U_ASSERT_ONLY err;
769 bool U_ASSERT_ONLY pass;
771 tex_obj->tex_width = tex_width;
772 tex_obj->tex_height = tex_height;
774 const VkImageCreateInfo image_create_info = {
775 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
777 .imageType = VK_IMAGE_TYPE_2D,
778 .format = tex_format,
779 .extent = {tex_width, tex_height, 1},
782 .samples = VK_SAMPLE_COUNT_1_BIT,
786 .initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED
788 VkMemoryAllocateInfo mem_alloc = {
789 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
792 .memoryTypeIndex = 0,
795 VkMemoryRequirements mem_reqs;
798 vkCreateImage(demo->device, &image_create_info, NULL, &tex_obj->image);
801 vkGetImageMemoryRequirements(demo->device, tex_obj->image, &mem_reqs);
803 mem_alloc.allocationSize = mem_reqs.size;
805 memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
806 required_props, &mem_alloc.memoryTypeIndex);
809 /* allocate memory */
810 err = vkAllocateMemory(demo->device, &mem_alloc, NULL, &tex_obj->mem);
814 err = vkBindImageMemory(demo->device, tex_obj->image, tex_obj->mem, 0);
817 if (required_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
818 const VkImageSubresource subres = {
819 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
823 VkSubresourceLayout layout;
827 vkGetImageSubresourceLayout(demo->device, tex_obj->image, &subres,
830 err = vkMapMemory(demo->device, tex_obj->mem, 0,
831 mem_alloc.allocationSize, 0, &data);
834 for (y = 0; y < tex_height; y++) {
835 uint32_t *row = (uint32_t *)((char *)data + layout.rowPitch * y);
836 for (x = 0; x < tex_width; x++)
837 row[x] = tex_colors[(x & 1) ^ (y & 1)];
840 vkUnmapMemory(demo->device, tex_obj->mem);
843 tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
844 demo_set_image_layout(demo, tex_obj->image, VK_IMAGE_ASPECT_COLOR_BIT,
845 VK_IMAGE_LAYOUT_PREINITIALIZED, tex_obj->imageLayout,
846 VK_ACCESS_HOST_WRITE_BIT);
847 /* setting the image layout does not reference the actual memory so no need
848 * to add a mem ref */
851 static void demo_destroy_texture_image(struct demo *demo,
852 struct texture_object *tex_obj) {
853 /* clean up staging resources */
854 vkDestroyImage(demo->device, tex_obj->image, NULL);
855 vkFreeMemory(demo->device, tex_obj->mem, NULL);
858 static void demo_prepare_textures(struct demo *demo) {
859 const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
860 VkFormatProperties props;
861 const uint32_t tex_colors[DEMO_TEXTURE_COUNT][2] = {
862 {0xffff0000, 0xff00ff00},
865 VkResult U_ASSERT_ONLY err;
867 vkGetPhysicalDeviceFormatProperties(demo->gpu, tex_format, &props);
869 for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
870 if ((props.linearTilingFeatures &
871 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) &&
872 !demo->use_staging_buffer) {
873 /* Device can texture using linear textures */
874 demo_prepare_texture_image(demo, tex_colors[i], &demo->textures[i],
875 VK_IMAGE_TILING_LINEAR,
876 VK_IMAGE_USAGE_SAMPLED_BIT,
877 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
878 } else if (props.optimalTilingFeatures &
879 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
880 /* Must use staging buffer to copy linear texture to optimized */
881 struct texture_object staging_texture;
883 memset(&staging_texture, 0, sizeof(staging_texture));
884 demo_prepare_texture_image(demo, tex_colors[i], &staging_texture,
885 VK_IMAGE_TILING_LINEAR,
886 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
887 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
889 demo_prepare_texture_image(
890 demo, tex_colors[i], &demo->textures[i],
891 VK_IMAGE_TILING_OPTIMAL,
892 (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
893 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
895 demo_set_image_layout(demo, staging_texture.image,
896 VK_IMAGE_ASPECT_COLOR_BIT,
897 staging_texture.imageLayout,
898 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
901 demo_set_image_layout(demo, demo->textures[i].image,
902 VK_IMAGE_ASPECT_COLOR_BIT,
903 demo->textures[i].imageLayout,
904 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
907 VkImageCopy copy_region = {
908 .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
909 .srcOffset = {0, 0, 0},
910 .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
911 .dstOffset = {0, 0, 0},
912 .extent = {staging_texture.tex_width,
913 staging_texture.tex_height, 1},
916 demo->setup_cmd, staging_texture.image,
917 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, demo->textures[i].image,
918 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region);
920 demo_set_image_layout(demo, demo->textures[i].image,
921 VK_IMAGE_ASPECT_COLOR_BIT,
922 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
923 demo->textures[i].imageLayout,
926 demo_flush_init_cmd(demo);
928 demo_destroy_texture_image(demo, &staging_texture);
930 /* Can't support VK_FORMAT_B8G8R8A8_UNORM !? */
931 assert(!"No support for B8G8R8A8_UNORM as texture image format");
934 const VkSamplerCreateInfo sampler = {
935 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
937 .magFilter = VK_FILTER_NEAREST,
938 .minFilter = VK_FILTER_NEAREST,
939 .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST,
940 .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT,
941 .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
942 .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
944 .anisotropyEnable = VK_FALSE,
946 .compareOp = VK_COMPARE_OP_NEVER,
949 .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
950 .unnormalizedCoordinates = VK_FALSE,
952 VkImageViewCreateInfo view = {
953 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
955 .image = VK_NULL_HANDLE,
956 .viewType = VK_IMAGE_VIEW_TYPE_2D,
957 .format = tex_format,
960 VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
961 VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A,
963 .subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
968 err = vkCreateSampler(demo->device, &sampler, NULL,
969 &demo->textures[i].sampler);
972 /* create image view */
973 view.image = demo->textures[i].image;
974 err = vkCreateImageView(demo->device, &view, NULL,
975 &demo->textures[i].view);
980 static void demo_prepare_vertices(struct demo *demo) {
982 const float vb[3][5] = {
983 /* position texcoord */
984 { -1.0f, -1.0f, 0.25f, 0.0f, 0.0f },
985 { 1.0f, -1.0f, 0.25f, 1.0f, 0.0f },
986 { 0.0f, 1.0f, 1.0f, 0.5f, 1.0f },
989 const VkBufferCreateInfo buf_info = {
990 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
993 .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
996 VkMemoryAllocateInfo mem_alloc = {
997 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1000 .memoryTypeIndex = 0,
1002 VkMemoryRequirements mem_reqs;
1003 VkResult U_ASSERT_ONLY err;
1004 bool U_ASSERT_ONLY pass;
1007 memset(&demo->vertices, 0, sizeof(demo->vertices));
1009 err = vkCreateBuffer(demo->device, &buf_info, NULL, &demo->vertices.buf);
1012 vkGetBufferMemoryRequirements(demo->device, demo->vertices.buf, &mem_reqs);
1015 mem_alloc.allocationSize = mem_reqs.size;
1016 pass = memory_type_from_properties(demo, mem_reqs.memoryTypeBits,
1017 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
1018 &mem_alloc.memoryTypeIndex);
1021 err = vkAllocateMemory(demo->device, &mem_alloc, NULL, &demo->vertices.mem);
1024 err = vkMapMemory(demo->device, demo->vertices.mem, 0,
1025 mem_alloc.allocationSize, 0, &data);
1028 memcpy(data, vb, sizeof(vb));
1030 vkUnmapMemory(demo->device, demo->vertices.mem);
1032 err = vkBindBufferMemory(demo->device, demo->vertices.buf,
1033 demo->vertices.mem, 0);
1036 demo->vertices.vi.sType =
1037 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1038 demo->vertices.vi.pNext = NULL;
1039 demo->vertices.vi.vertexBindingDescriptionCount = 1;
1040 demo->vertices.vi.pVertexBindingDescriptions = demo->vertices.vi_bindings;
1041 demo->vertices.vi.vertexAttributeDescriptionCount = 2;
1042 demo->vertices.vi.pVertexAttributeDescriptions = demo->vertices.vi_attrs;
1044 demo->vertices.vi_bindings[0].binding = VERTEX_BUFFER_BIND_ID;
1045 demo->vertices.vi_bindings[0].stride = sizeof(vb[0]);
1046 demo->vertices.vi_bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
1048 demo->vertices.vi_attrs[0].binding = VERTEX_BUFFER_BIND_ID;
1049 demo->vertices.vi_attrs[0].location = 0;
1050 demo->vertices.vi_attrs[0].format = VK_FORMAT_R32G32B32_SFLOAT;
1051 demo->vertices.vi_attrs[0].offset = 0;
1053 demo->vertices.vi_attrs[1].binding = VERTEX_BUFFER_BIND_ID;
1054 demo->vertices.vi_attrs[1].location = 1;
1055 demo->vertices.vi_attrs[1].format = VK_FORMAT_R32G32_SFLOAT;
1056 demo->vertices.vi_attrs[1].offset = sizeof(float) * 3;
1059 static void demo_prepare_descriptor_layout(struct demo *demo) {
1060 const VkDescriptorSetLayoutBinding layout_binding = {
1062 .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1063 .descriptorCount = DEMO_TEXTURE_COUNT,
1064 .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
1065 .pImmutableSamplers = NULL,
1067 const VkDescriptorSetLayoutCreateInfo descriptor_layout = {
1068 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1071 .pBindings = &layout_binding,
1073 VkResult U_ASSERT_ONLY err;
1075 err = vkCreateDescriptorSetLayout(demo->device, &descriptor_layout, NULL,
1076 &demo->desc_layout);
1079 const VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {
1080 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1082 .setLayoutCount = 1,
1083 .pSetLayouts = &demo->desc_layout,
1086 err = vkCreatePipelineLayout(demo->device, &pPipelineLayoutCreateInfo, NULL,
1087 &demo->pipeline_layout);
1091 static void demo_prepare_render_pass(struct demo *demo) {
1092 const VkAttachmentDescription attachments[2] = {
1095 .format = demo->format,
1096 .samples = VK_SAMPLE_COUNT_1_BIT,
1097 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
1098 .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
1099 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
1100 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1101 .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1102 .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1106 .format = demo->depth.format,
1107 .samples = VK_SAMPLE_COUNT_1_BIT,
1108 .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
1109 .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1110 .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
1111 .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
1113 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1115 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1118 const VkAttachmentReference color_reference = {
1119 .attachment = 0, .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1121 const VkAttachmentReference depth_reference = {
1123 .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1125 const VkSubpassDescription subpass = {
1126 .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
1128 .inputAttachmentCount = 0,
1129 .pInputAttachments = NULL,
1130 .colorAttachmentCount = 1,
1131 .pColorAttachments = &color_reference,
1132 .pResolveAttachments = NULL,
1133 .pDepthStencilAttachment = &depth_reference,
1134 .preserveAttachmentCount = 0,
1135 .pPreserveAttachments = NULL,
1137 const VkRenderPassCreateInfo rp_info = {
1138 .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1140 .attachmentCount = 2,
1141 .pAttachments = attachments,
1143 .pSubpasses = &subpass,
1144 .dependencyCount = 0,
1145 .pDependencies = NULL,
1147 VkResult U_ASSERT_ONLY err;
1149 err = vkCreateRenderPass(demo->device, &rp_info, NULL, &demo->render_pass);
1153 static VkShaderModule
1154 demo_prepare_shader_module(struct demo *demo, const void *code, size_t size) {
1155 VkShaderModuleCreateInfo moduleCreateInfo;
1156 VkShaderModule module;
1157 VkResult U_ASSERT_ONLY err;
1159 moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1160 moduleCreateInfo.pNext = NULL;
1162 moduleCreateInfo.codeSize = size;
1163 moduleCreateInfo.pCode = code;
1164 moduleCreateInfo.flags = 0;
1165 err = vkCreateShaderModule(demo->device, &moduleCreateInfo, NULL, &module);
1171 char *demo_read_spv(const char *filename, size_t *psize) {
1176 FILE *fp = fopen(filename, "rb");
1180 fseek(fp, 0L, SEEK_END);
1183 fseek(fp, 0L, SEEK_SET);
1185 shader_code = malloc(size);
1186 retVal = fread(shader_code, size, 1, fp);
1196 static unsigned char vert_spirv_bin[] = {
1197 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x18, 0x00, 0x00, 0x00,
1198 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00,
1199 0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30,
1200 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1201 0x0F, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
1202 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
1203 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00,
1204 0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73, 0x65, 0x70, 0x61, 0x72,
1205 0x61, 0x74, 0x65, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5F, 0x6F, 0x62, 0x6A, 0x65, 0x63,
1206 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73,
1207 0x68, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x5F, 0x6C, 0x61, 0x6E, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5F,
1208 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6B, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
1209 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00,
1210 0x74, 0x65, 0x78, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
1211 0x0B, 0x00, 0x00, 0x00, 0x61, 0x74, 0x74, 0x72, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00,
1212 0x0E, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78,
1213 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214 0x67, 0x6C, 0x5F, 0x50, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x05, 0x00, 0x03, 0x00,
1215 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x14, 0x00, 0x00, 0x00,
1216 0x70, 0x6F, 0x73, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00,
1217 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00,
1218 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1219 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00,
1220 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00,
1221 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
1222 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
1223 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1224 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1225 0x07, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
1226 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1227 0x07, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
1228 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
1229 0x04, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
1230 0x20, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
1231 0x3B, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1232 0x15, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1233 0x2B, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1234 0x20, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
1235 0x3B, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1236 0x20, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
1237 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1238 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
1239 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00,
1240 0x09, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00,
1241 0x15, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00,
1242 0x17, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00,
1243 0x17, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
1246 static VkShaderModule demo_prepare_vs(struct demo *demo) {
1247 void *vertShaderCode;
1250 /* insert shader binary for test convenience */
1251 /* vertShaderCode = demo_read_spv("tri-vert.spv", &size);*/
1252 vertShaderCode = vert_spirv_bin;
1253 size = sizeof(vert_spirv_bin)/sizeof(unsigned char);
1255 demo->vert_shader_module =
1256 demo_prepare_shader_module(demo, vertShaderCode, size);
1258 /*free(vertShaderCode);*/
1260 return demo->vert_shader_module;
1263 static unsigned char frag_spirv_bin[] = {
1264 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00,
1265 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00,
1266 0x01, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30,
1267 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1268 0x0F, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
1269 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
1270 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
1271 0x90, 0x01, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41, 0x52, 0x42, 0x5F, 0x73,
1272 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5F, 0x6F,
1273 0x62, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x47, 0x4C, 0x5F, 0x41,
1274 0x52, 0x42, 0x5F, 0x73, 0x68, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x5F, 0x6C, 0x61, 0x6E, 0x67, 0x75,
1275 0x61, 0x67, 0x65, 0x5F, 0x34, 0x32, 0x30, 0x70, 0x61, 0x63, 0x6B, 0x00, 0x05, 0x00, 0x04, 0x00,
1276 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
1277 0x09, 0x00, 0x00, 0x00, 0x75, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00,
1278 0x05, 0x00, 0x03, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x00, 0x05, 0x00, 0x05, 0x00,
1279 0x11, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x63, 0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00,
1280 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1281 0x47, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1282 0x47, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1283 0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1284 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
1285 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
1286 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1287 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
1288 0x3B, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1289 0x19, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1291 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,
1292 0x20, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
1293 0x3B, 0x00, 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1294 0x17, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1295 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
1296 0x3B, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1297 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1298 0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
1299 0x0B, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
1300 0x0F, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00,
1301 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
1302 0x3E, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00,
1303 0x38, 0x00, 0x01, 0x00,
1306 static VkShaderModule demo_prepare_fs(struct demo *demo) {
1307 void *fragShaderCode;
1310 /* insert shader binary for test convenience */
1311 /*fragShaderCode = demo_read_spv("tri-frag.spv", &size);*/
1312 fragShaderCode = frag_spirv_bin;
1313 size = sizeof(frag_spirv_bin)/sizeof(unsigned char);
1315 demo->frag_shader_module =
1316 demo_prepare_shader_module(demo, fragShaderCode, size);
1318 /*free(fragShaderCode);*/
1320 return demo->frag_shader_module;
1323 static void demo_prepare_pipeline(struct demo *demo) {
1324 VkGraphicsPipelineCreateInfo pipeline;
1325 VkPipelineCacheCreateInfo pipelineCache;
1327 VkPipelineVertexInputStateCreateInfo vi;
1328 VkPipelineInputAssemblyStateCreateInfo ia;
1329 VkPipelineRasterizationStateCreateInfo rs;
1330 VkPipelineColorBlendStateCreateInfo cb;
1331 VkPipelineDepthStencilStateCreateInfo ds;
1332 VkPipelineViewportStateCreateInfo vp;
1333 VkPipelineMultisampleStateCreateInfo ms;
1334 VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE];
1335 VkPipelineDynamicStateCreateInfo dynamicState;
1337 VkResult U_ASSERT_ONLY err;
1339 memset(dynamicStateEnables, 0, sizeof dynamicStateEnables);
1340 memset(&dynamicState, 0, sizeof dynamicState);
1341 dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1342 dynamicState.pDynamicStates = dynamicStateEnables;
1344 memset(&pipeline, 0, sizeof(pipeline));
1345 pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1346 pipeline.layout = demo->pipeline_layout;
1348 vi = demo->vertices.vi;
1350 memset(&ia, 0, sizeof(ia));
1351 ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1352 ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1354 memset(&rs, 0, sizeof(rs));
1355 rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1356 rs.polygonMode = VK_POLYGON_MODE_FILL;
1357 rs.cullMode = VK_CULL_MODE_BACK_BIT;
1358 rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
1359 rs.depthClampEnable = VK_FALSE;
1360 rs.rasterizerDiscardEnable = VK_FALSE;
1361 rs.depthBiasEnable = VK_FALSE;
1363 memset(&cb, 0, sizeof(cb));
1364 cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1365 VkPipelineColorBlendAttachmentState att_state[1];
1366 memset(att_state, 0, sizeof(att_state));
1367 att_state[0].colorWriteMask = 0xf;
1368 att_state[0].blendEnable = VK_FALSE;
1369 cb.attachmentCount = 1;
1370 cb.pAttachments = att_state;
1372 memset(&vp, 0, sizeof(vp));
1373 vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1374 vp.viewportCount = 1;
1375 dynamicStateEnables[dynamicState.dynamicStateCount++] =
1376 VK_DYNAMIC_STATE_VIEWPORT;
1377 vp.scissorCount = 1;
1378 dynamicStateEnables[dynamicState.dynamicStateCount++] =
1379 VK_DYNAMIC_STATE_SCISSOR;
1381 memset(&ds, 0, sizeof(ds));
1382 ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1383 ds.depthTestEnable = VK_TRUE;
1384 ds.depthWriteEnable = VK_TRUE;
1385 ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
1386 ds.depthBoundsTestEnable = VK_FALSE;
1387 ds.back.failOp = VK_STENCIL_OP_KEEP;
1388 ds.back.passOp = VK_STENCIL_OP_KEEP;
1389 ds.back.compareOp = VK_COMPARE_OP_ALWAYS;
1390 ds.stencilTestEnable = VK_FALSE;
1393 memset(&ms, 0, sizeof(ms));
1394 ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1395 ms.pSampleMask = NULL;
1396 ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
1398 // Two stages: vs and fs
1399 pipeline.stageCount = 2;
1400 VkPipelineShaderStageCreateInfo shaderStages[2];
1401 memset(&shaderStages, 0, 2 * sizeof(VkPipelineShaderStageCreateInfo));
1403 shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1404 shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
1405 shaderStages[0].module = demo_prepare_vs(demo);
1406 shaderStages[0].pName = "main";
1408 shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1409 shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
1410 shaderStages[1].module = demo_prepare_fs(demo);
1411 shaderStages[1].pName = "main";
1413 pipeline.pVertexInputState = &vi;
1414 pipeline.pInputAssemblyState = &ia;
1415 pipeline.pRasterizationState = &rs;
1416 pipeline.pColorBlendState = &cb;
1417 pipeline.pMultisampleState = &ms;
1418 pipeline.pViewportState = &vp;
1419 pipeline.pDepthStencilState = &ds;
1420 pipeline.pStages = shaderStages;
1421 pipeline.renderPass = demo->render_pass;
1422 pipeline.pDynamicState = &dynamicState;
1424 memset(&pipelineCache, 0, sizeof(pipelineCache));
1425 pipelineCache.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1427 err = vkCreatePipelineCache(demo->device, &pipelineCache, NULL,
1428 &demo->pipelineCache);
1430 err = vkCreateGraphicsPipelines(demo->device, demo->pipelineCache, 1,
1431 &pipeline, NULL, &demo->pipeline);
1434 vkDestroyPipelineCache(demo->device, demo->pipelineCache, NULL);
1436 vkDestroyShaderModule(demo->device, demo->frag_shader_module, NULL);
1437 vkDestroyShaderModule(demo->device, demo->vert_shader_module, NULL);
1440 static void demo_prepare_descriptor_pool(struct demo *demo) {
1441 const VkDescriptorPoolSize type_count = {
1442 .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
1443 .descriptorCount = DEMO_TEXTURE_COUNT,
1445 const VkDescriptorPoolCreateInfo descriptor_pool = {
1446 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1450 .pPoolSizes = &type_count,
1452 VkResult U_ASSERT_ONLY err;
1454 err = vkCreateDescriptorPool(demo->device, &descriptor_pool, NULL,
1459 static void demo_prepare_descriptor_set(struct demo *demo) {
1460 VkDescriptorImageInfo tex_descs[DEMO_TEXTURE_COUNT];
1461 VkWriteDescriptorSet write;
1462 VkResult U_ASSERT_ONLY err;
1465 VkDescriptorSetAllocateInfo alloc_info = {
1466 .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1468 .descriptorPool = demo->desc_pool,
1469 .descriptorSetCount = 1,
1470 .pSetLayouts = &demo->desc_layout};
1471 err = vkAllocateDescriptorSets(demo->device, &alloc_info, &demo->desc_set);
1474 memset(&tex_descs, 0, sizeof(tex_descs));
1475 for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
1476 tex_descs[i].sampler = demo->textures[i].sampler;
1477 tex_descs[i].imageView = demo->textures[i].view;
1478 tex_descs[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
1481 memset(&write, 0, sizeof(write));
1482 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1483 write.dstSet = demo->desc_set;
1484 write.descriptorCount = DEMO_TEXTURE_COUNT;
1485 write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1486 write.pImageInfo = tex_descs;
1488 vkUpdateDescriptorSets(demo->device, 1, &write, 0, NULL);
1491 static void demo_prepare_framebuffers(struct demo *demo) {
1492 VkImageView attachments[2];
1493 attachments[1] = demo->depth.view;
1495 const VkFramebufferCreateInfo fb_info = {
1496 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
1498 .renderPass = demo->render_pass,
1499 .attachmentCount = 2,
1500 .pAttachments = attachments,
1501 .width = demo->width,
1502 .height = demo->height,
1505 VkResult U_ASSERT_ONLY err;
1508 demo->framebuffers = (VkFramebuffer *)malloc(demo->swapchainImageCount *
1509 sizeof(VkFramebuffer));
1510 assert(demo->framebuffers);
1512 for (i = 0; i < demo->swapchainImageCount; i++) {
1513 attachments[0] = demo->buffers[i].view;
1514 err = vkCreateFramebuffer(demo->device, &fb_info, NULL,
1515 &demo->framebuffers[i]);
1520 static void demo_prepare(struct demo *demo) {
1521 VkResult U_ASSERT_ONLY err;
1523 const VkCommandPoolCreateInfo cmd_pool_info = {
1524 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
1526 .queueFamilyIndex = demo->graphics_queue_node_index,
1527 .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1529 err = vkCreateCommandPool(demo->device, &cmd_pool_info, NULL,
1533 const VkCommandBufferAllocateInfo cmd = {
1534 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1536 .commandPool = demo->cmd_pool,
1537 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1538 .commandBufferCount = 1,
1540 err = vkAllocateCommandBuffers(demo->device, &cmd, &demo->draw_cmd);
1543 demo_prepare_buffers(demo);
1544 demo_prepare_depth(demo);
1545 demo_prepare_textures(demo);
1546 demo_prepare_vertices(demo);
1547 demo_prepare_descriptor_layout(demo);
1548 demo_prepare_render_pass(demo);
1549 demo_prepare_pipeline(demo);
1551 demo_prepare_descriptor_pool(demo);
1552 demo_prepare_descriptor_set(demo);
1554 demo_prepare_framebuffers(demo);
1556 demo->prepared = true;
1559 static void demo_run(struct demo *demo)
1563 if (demo->depthStencil > 0.99f)
1564 demo->depthIncrement = -0.001f;
1565 if (demo->depthStencil < 0.8f)
1566 demo->depthIncrement = 0.001f;
1568 demo->depthStencil += demo->depthIncrement;
1570 // Wait for work to finish before updating MVP.
1571 vkDeviceWaitIdle(demo->device);
1573 if (demo->frameCount != INT32_MAX && demo->curFrame == demo->frameCount)
1578 * Return 1 (true) if all layer names specified in check_names
1579 * can be found in given layer properties.
1581 static VkBool32 demo_check_layers(uint32_t check_count, char **check_names,
1582 uint32_t layer_count,
1583 VkLayerProperties *layers) {
1585 for (i = 0; i < check_count; i++) {
1587 for (j = 0; j < layer_count; j++) {
1588 if (!strcmp(check_names[i], layers[j].layerName)) {
1594 fprintf(stderr, "Cannot find layer: %s\n", check_names[i]);
1601 static void demo_init_vk(struct demo *demo) {
1603 uint32_t instance_extension_count = 0;
1604 uint32_t instance_layer_count = 0;
1605 uint32_t device_validation_layer_count = 0;
1606 char **instance_validation_layers = NULL;
1608 demo->enabled_extension_count = 0;
1609 demo->enabled_layer_count = 0;
1611 char *instance_validation_layers_alt1[] = {
1612 "VK_LAYER_LUNARG_standard_validation"
1615 char *instance_validation_layers_alt2[] = {
1616 "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
1617 "VK_LAYER_LUNARG_device_limits", "VK_LAYER_LUNARG_object_tracker",
1618 "VK_LAYER_LUNARG_image", "VK_LAYER_LUNARG_core_validation",
1619 "VK_LAYER_LUNARG_swapchain", "VK_LAYER_GOOGLE_unique_objects"
1622 /* Look for validation layers */
1623 VkBool32 validation_found = 0;
1624 if (demo->validate) {
1626 err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
1629 instance_validation_layers = instance_validation_layers_alt1;
1630 if (instance_layer_count > 0) {
1631 VkLayerProperties *instance_layers =
1632 malloc(sizeof (VkLayerProperties) * instance_layer_count);
1633 err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
1638 validation_found = demo_check_layers(
1639 ARRAY_SIZE(instance_validation_layers_alt1),
1640 instance_validation_layers, instance_layer_count,
1642 if (validation_found) {
1643 demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt1);
1644 demo->device_validation_layers[0] = "VK_LAYER_LUNARG_standard_validation";
1645 device_validation_layer_count = 1;
1647 // use alternative set of validation layers
1648 instance_validation_layers = instance_validation_layers_alt2;
1649 demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt2);
1650 validation_found = demo_check_layers(
1651 ARRAY_SIZE(instance_validation_layers_alt2),
1652 instance_validation_layers, instance_layer_count,
1654 device_validation_layer_count =
1655 ARRAY_SIZE(instance_validation_layers_alt2);
1656 for (i = 0; i < device_validation_layer_count; i++) {
1657 demo->device_validation_layers[i] =
1658 instance_validation_layers[i];
1661 free(instance_layers);
1664 if (!validation_found) {
1665 ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find"
1666 "required validation layer.\n\n"
1667 "Please look at the Getting Started guide for additional "
1669 "vkCreateInstance Failure");
1673 /* Look for instance extensions */
1674 VkBool32 surfaceExtFound = 0;
1675 VkBool32 platformSurfaceExtFound = 0;
1676 memset(demo->extension_names, 0, sizeof(demo->extension_names));
1679 err = vkEnumerateInstanceExtensionProperties(
1680 NULL, &instance_extension_count, NULL);
1683 if (instance_extension_count > 0) {
1685 VkExtensionProperties *instance_extensions =
1686 malloc(sizeof(VkExtensionProperties) * instance_extension_count);
1687 err = vkEnumerateInstanceExtensionProperties(
1688 NULL, &instance_extension_count, instance_extensions);
1690 for (i = 0; i < instance_extension_count; i++) {
1691 if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME,
1692 instance_extensions[i].extensionName)) {
1693 surfaceExtFound = 1;
1694 demo->extension_names[demo->enabled_extension_count++] =
1695 VK_KHR_SURFACE_EXTENSION_NAME;
1697 if (!strcmp(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
1698 instance_extensions[i].extensionName)) {
1699 platformSurfaceExtFound = 1;
1700 demo->extension_names[demo->enabled_extension_count++] =
1701 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
1703 if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
1704 instance_extensions[i].extensionName)) {
1705 if (demo->validate) {
1706 demo->extension_names[demo->enabled_extension_count++] =
1707 VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
1710 assert(demo->enabled_extension_count < 64);
1713 free(instance_extensions);
1716 if (!surfaceExtFound) {
1717 ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
1718 "the " VK_KHR_SURFACE_EXTENSION_NAME
1719 " extension.\n\nDo you have a compatible "
1720 "Vulkan installable client driver (ICD) installed?\nPlease "
1721 "look at the Getting Started guide for additional "
1723 "vkCreateInstance Failure");
1725 if (!platformSurfaceExtFound) {
1726 ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
1727 "the " VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
1728 " extension.\n\nDo you have a compatible "
1729 "Vulkan installable client driver (ICD) installed?\nPlease "
1730 "look at the Getting Started guide for additional "
1732 "vkCreateInstance Failure");
1735 SDL_Vulkan_GetInstanceExtensions(demo->sdl_window, &(demo->enabled_extension_count), demo->extension_names);
1737 const VkApplicationInfo app = {
1738 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
1740 .pApplicationName = APP_SHORT_NAME,
1741 .applicationVersion = 0,
1742 .pEngineName = APP_SHORT_NAME,
1744 .apiVersion = VK_API_VERSION_1_0,
1746 VkInstanceCreateInfo inst_info = {
1747 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
1749 .pApplicationInfo = &app,
1750 .enabledLayerCount = demo->enabled_layer_count,
1751 .ppEnabledLayerNames = (const char *const *)instance_validation_layers,
1752 .enabledExtensionCount = demo->enabled_extension_count,
1753 .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
1758 err = vkCreateInstance(&inst_info, NULL, &demo->inst);
1759 if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
1760 ERR_EXIT("Cannot find a compatible Vulkan installable client driver "
1761 "(ICD).\n\nPlease look at the Getting Started guide for "
1762 "additional information.\n",
1763 "vkCreateInstance Failure");
1764 } else if (err == VK_ERROR_EXTENSION_NOT_PRESENT) {
1765 ERR_EXIT("Cannot find a specified extension library"
1766 ".\nMake sure your layers path is set appropriately\n",
1767 "vkCreateInstance Failure");
1769 ERR_EXIT("vkCreateInstance failed.\n\nDo you have a compatible Vulkan "
1770 "installable client driver (ICD) installed?\nPlease look at "
1771 "the Getting Started guide for additional information.\n",
1772 "vkCreateInstance Failure");
1775 /* Make initial call to query gpu_count, then second call for gpu info*/
1776 err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL);
1777 assert(!err && gpu_count > 0);
1779 if (gpu_count > 0) {
1780 VkPhysicalDevice *physical_devices =
1781 malloc(sizeof(VkPhysicalDevice) * gpu_count);
1782 err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count,
1785 /* For tri demo we just grab the first physical device */
1786 demo->gpu = physical_devices[0];
1787 free(physical_devices);
1789 ERR_EXIT("vkEnumeratePhysicalDevices reported zero accessible devices."
1790 "\n\nDo you have a compatible Vulkan installable client"
1791 " driver (ICD) installed?\nPlease look at the Getting Started"
1792 " guide for additional information.\n",
1793 "vkEnumeratePhysicalDevices Failure");
1796 /* Look for validation layers */
1797 if (demo->validate) {
1798 validation_found = 0;
1799 demo->enabled_layer_count = 0;
1800 uint32_t device_layer_count = 0;
1802 vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count, NULL);
1805 if (device_layer_count > 0) {
1806 VkLayerProperties *device_layers =
1807 malloc(sizeof (VkLayerProperties) * device_layer_count);
1808 err = vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count,
1813 validation_found = demo_check_layers(device_validation_layer_count,
1814 demo->device_validation_layers,
1817 demo->enabled_layer_count = device_validation_layer_count;
1819 free(device_layers);
1822 if (!validation_found) {
1823 ERR_EXIT("vkEnumerateDeviceLayerProperties failed to find "
1824 "a required validation layer.\n\n"
1825 "Please look at the Getting Started guide for additional "
1827 "vkCreateDevice Failure");
1831 /* Look for device extensions */
1832 uint32_t device_extension_count = 0;
1833 VkBool32 swapchainExtFound = 0;
1834 demo->enabled_extension_count = 0;
1835 memset(demo->extension_names, 0, sizeof(demo->extension_names));
1837 err = vkEnumerateDeviceExtensionProperties(demo->gpu, NULL,
1838 &device_extension_count, NULL);
1841 if (device_extension_count > 0) {
1843 VkExtensionProperties *device_extensions =
1844 malloc(sizeof(VkExtensionProperties) * device_extension_count);
1845 err = vkEnumerateDeviceExtensionProperties(
1846 demo->gpu, NULL, &device_extension_count, device_extensions);
1849 for (i = 0; i < device_extension_count; i++) {
1850 if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME,
1851 device_extensions[i].extensionName)) {
1852 swapchainExtFound = 1;
1853 demo->extension_names[demo->enabled_extension_count++] =
1854 VK_KHR_SWAPCHAIN_EXTENSION_NAME;
1856 assert(demo->enabled_extension_count < 64);
1859 free(device_extensions);
1862 if (!swapchainExtFound) {
1863 ERR_EXIT("vkEnumerateDeviceExtensionProperties failed to find "
1864 "the " VK_KHR_SWAPCHAIN_EXTENSION_NAME
1865 " extension.\n\nDo you have a compatible "
1866 "Vulkan installable client driver (ICD) installed?\nPlease "
1867 "look at the Getting Started guide for additional "
1869 "vkCreateInstance Failure");
1872 if (demo->validate) {
1873 demo->CreateDebugReportCallback =
1874 (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(
1875 demo->inst, "vkCreateDebugReportCallbackEXT");
1876 demo->DestroyDebugReportCallback =
1877 (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(
1878 demo->inst, "vkDestroyDebugReportCallbackEXT");
1879 if (!demo->CreateDebugReportCallback) {
1881 "GetProcAddr: Unable to find vkCreateDebugReportCallbackEXT\n",
1882 "vkGetProcAddr Failure");
1884 if (!demo->DestroyDebugReportCallback) {
1886 "GetProcAddr: Unable to find vkDestroyDebugReportCallbackEXT\n",
1887 "vkGetProcAddr Failure");
1889 demo->DebugReportMessage =
1890 (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(
1891 demo->inst, "vkDebugReportMessageEXT");
1892 if (!demo->DebugReportMessage) {
1893 ERR_EXIT("GetProcAddr: Unable to find vkDebugReportMessageEXT\n",
1894 "vkGetProcAddr Failure");
1897 VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
1898 dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
1899 dbgCreateInfo.flags =
1900 VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
1901 dbgCreateInfo.pfnCallback = demo->use_break ? BreakCallback : dbgFunc;
1902 dbgCreateInfo.pUserData = NULL;
1903 dbgCreateInfo.pNext = NULL;
1904 err = demo->CreateDebugReportCallback(demo->inst, &dbgCreateInfo, NULL,
1905 &demo->msg_callback);
1909 case VK_ERROR_OUT_OF_HOST_MEMORY:
1910 ERR_EXIT("CreateDebugReportCallback: out of host memory\n",
1911 "CreateDebugReportCallback Failure");
1914 ERR_EXIT("CreateDebugReportCallback: unknown failure\n",
1915 "CreateDebugReportCallback Failure");
1920 // Having these GIPA queries of device extension entry points both
1921 // BEFORE and AFTER vkCreateDevice is a good test for the loader
1922 GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
1923 GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceFormatsKHR);
1924 GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfacePresentModesKHR);
1925 GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceSupportKHR);
1926 GET_INSTANCE_PROC_ADDR(demo->inst, CreateSwapchainKHR);
1927 GET_INSTANCE_PROC_ADDR(demo->inst, DestroySwapchainKHR);
1928 GET_INSTANCE_PROC_ADDR(demo->inst, GetSwapchainImagesKHR);
1929 GET_INSTANCE_PROC_ADDR(demo->inst, AcquireNextImageKHR);
1930 GET_INSTANCE_PROC_ADDR(demo->inst, QueuePresentKHR);
1932 vkGetPhysicalDeviceProperties(demo->gpu, &demo->gpu_props);
1934 // Query with NULL data to get count
1935 vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu, &demo->queue_count,
1938 demo->queue_props = (VkQueueFamilyProperties *)malloc(
1939 demo->queue_count * sizeof(VkQueueFamilyProperties));
1940 vkGetPhysicalDeviceQueueFamilyProperties(demo->gpu, &demo->queue_count,
1942 assert(demo->queue_count >= 1);
1944 VkPhysicalDeviceFeatures features;
1945 vkGetPhysicalDeviceFeatures(demo->gpu, &features);
1948 static void demo_init_device(struct demo *demo) {
1949 VkResult U_ASSERT_ONLY err;
1951 float queue_priorities[1] = {0.0};
1952 const VkDeviceQueueCreateInfo queue = {
1953 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
1955 .queueFamilyIndex = demo->graphics_queue_node_index,
1957 .pQueuePriorities = queue_priorities};
1959 VkPhysicalDeviceFeatures features = {
1960 .shaderClipDistance = VK_TRUE,
1963 VkDeviceCreateInfo device = {
1964 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
1966 .queueCreateInfoCount = 1,
1967 .pQueueCreateInfos = &queue,
1968 .enabledLayerCount = demo->enabled_layer_count,
1969 .ppEnabledLayerNames =
1970 (const char *const *)((demo->validate)
1971 ? demo->device_validation_layers
1973 .enabledExtensionCount = demo->enabled_extension_count,
1974 .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
1975 .pEnabledFeatures = &features,
1978 err = vkCreateDevice(demo->gpu, &device, NULL, &demo->device);
1982 static void demo_init_vk_swapchain(struct demo *demo) {
1983 VkResult U_ASSERT_ONLY err;
1986 SDL_Vulkan_CreateSurface(demo->sdl_window, (SDL_vulkanInstance)demo->inst, (SDL_vulkanSurface*)&demo->surface);
1989 // Iterate over each queue to learn whether it supports presenting:
1990 VkBool32 *supportsPresent =
1991 (VkBool32 *)malloc(demo->queue_count * sizeof(VkBool32));
1992 for (i = 0; i < demo->queue_count; i++) {
1993 demo->fpGetPhysicalDeviceSurfaceSupportKHR(demo->gpu, i, demo->surface,
1994 &supportsPresent[i]);
1997 // Search for a graphics and a present queue in the array of queue
1998 // families, try to find one that supports both
1999 uint32_t graphicsQueueNodeIndex = UINT32_MAX;
2000 uint32_t presentQueueNodeIndex = UINT32_MAX;
2001 for (i = 0; i < demo->queue_count; i++) {
2002 if ((demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
2003 if (graphicsQueueNodeIndex == UINT32_MAX) {
2004 graphicsQueueNodeIndex = i;
2007 if (supportsPresent[i] == VK_TRUE) {
2008 graphicsQueueNodeIndex = i;
2009 presentQueueNodeIndex = i;
2014 if (presentQueueNodeIndex == UINT32_MAX) {
2015 // If didn't find a queue that supports both graphics and present, then
2016 // find a separate present queue.
2018 for (i = 0; i < demo->queue_count; ++i) {
2019 if (supportsPresent[i] == VK_TRUE) {
2020 presentQueueNodeIndex = i;
2025 free(supportsPresent);
2027 // Generate error if could not find both a graphics and a present queue
2028 if (graphicsQueueNodeIndex == UINT32_MAX ||
2029 presentQueueNodeIndex == UINT32_MAX) {
2030 ERR_EXIT("Could not find a graphics and a present queue\n",
2031 "Swapchain Initialization Failure");
2034 // TODO: Add support for separate queues, including presentation,
2035 // synchronization, and appropriate tracking for QueueSubmit.
2036 // NOTE: While it is possible for an application to use a separate graphics
2037 // and a present queues, this demo program assumes it is only using
2039 if (graphicsQueueNodeIndex != presentQueueNodeIndex) {
2040 ERR_EXIT("Could not find a common graphics and a present queue\n",
2041 "Swapchain Initialization Failure");
2044 demo->graphics_queue_node_index = graphicsQueueNodeIndex;
2046 demo_init_device(demo);
2048 vkGetDeviceQueue(demo->device, demo->graphics_queue_node_index, 0,
2051 // Get the list of VkFormat's that are supported:
2052 uint32_t formatCount;
2053 err = demo->fpGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface,
2054 &formatCount, NULL);
2056 VkSurfaceFormatKHR *surfFormats =
2057 (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
2058 err = demo->fpGetPhysicalDeviceSurfaceFormatsKHR(demo->gpu, demo->surface,
2059 &formatCount, surfFormats);
2061 // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
2062 // the surface has no preferred format. Otherwise, at least one
2063 // supported format will be returned.
2064 if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED) {
2065 demo->format = VK_FORMAT_B8G8R8A8_UNORM;
2067 assert(formatCount >= 1);
2068 demo->format = surfFormats[0].format;
2070 demo->color_space = surfFormats[0].colorSpace;
2075 // Get Memory information and properties
2076 vkGetPhysicalDeviceMemoryProperties(demo->gpu, &demo->memory_properties);
2079 static void argc_init(struct demo *demo, int argc, char *argv[])
2083 memset(demo, 0, sizeof(*demo));
2084 demo->frameCount = INT32_MAX;
2086 for (i = 1; i < argc; i++) {
2087 if (strcmp(argv[i], "--use_staging") == 0) {
2088 demo->use_staging_buffer = true;
2091 if (strcmp(argv[i], "--break") == 0) {
2092 demo->use_break = true;
2095 if (strcmp(argv[i], "--validate") == 0) {
2096 demo->validate = true;
2099 if (strcmp(argv[i], "--c") == 0 && demo->frameCount == INT32_MAX &&
2100 i < argc - 1 && sscanf(argv[i + 1], "%d", &demo->frameCount) == 1 &&
2101 demo->frameCount >= 0) {
2106 fprintf(stderr, "Usage:\n %s [--use_staging] [--validate] [--break] "
2107 "[--c <framecount>]\n",
2114 static void demo_cleanup(struct demo *demo) {
2117 demo->prepared = false;
2119 for (i = 0; i < demo->swapchainImageCount; i++) {
2120 vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
2122 free(demo->framebuffers);
2123 vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
2125 if (demo->setup_cmd) {
2126 vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->setup_cmd);
2128 vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->draw_cmd);
2129 vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL);
2131 vkDestroyPipeline(demo->device, demo->pipeline, NULL);
2132 vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
2133 vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
2134 vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
2136 vkDestroyBuffer(demo->device, demo->vertices.buf, NULL);
2137 vkFreeMemory(demo->device, demo->vertices.mem, NULL);
2139 for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
2140 vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
2141 vkDestroyImage(demo->device, demo->textures[i].image, NULL);
2142 vkFreeMemory(demo->device, demo->textures[i].mem, NULL);
2143 vkDestroySampler(demo->device, demo->textures[i].sampler, NULL);
2146 for (i = 0; i < demo->swapchainImageCount; i++) {
2147 vkDestroyImageView(demo->device, demo->buffers[i].view, NULL);
2150 vkDestroyImageView(demo->device, demo->depth.view, NULL);
2151 vkDestroyImage(demo->device, demo->depth.image, NULL);
2152 vkFreeMemory(demo->device, demo->depth.mem, NULL);
2154 demo->fpDestroySwapchainKHR(demo->device, demo->swapchain, NULL);
2155 free(demo->buffers);
2157 vkDestroyDevice(demo->device, NULL);
2158 if (demo->validate) {
2159 demo->DestroyDebugReportCallback(demo->inst, demo->msg_callback, NULL);
2161 vkDestroySurfaceKHR(demo->inst, demo->surface, NULL);
2162 vkDestroyInstance(demo->inst, NULL);
2164 free(demo->queue_props);
2167 static void demo_resize(struct demo *demo) {
2170 // Don't react to resize until after first initialization.
2171 if (!demo->prepared) {
2174 // In order to properly resize the window, we must re-create the swapchain
2175 // AND redo the command buffers, etc.
2177 // First, perform part of the demo_cleanup() function:
2178 demo->prepared = false;
2180 for (i = 0; i < demo->swapchainImageCount; i++) {
2181 vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
2183 free(demo->framebuffers);
2184 vkDestroyDescriptorPool(demo->device, demo->desc_pool, NULL);
2186 if (demo->setup_cmd) {
2187 vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->setup_cmd);
2189 vkFreeCommandBuffers(demo->device, demo->cmd_pool, 1, &demo->draw_cmd);
2190 vkDestroyCommandPool(demo->device, demo->cmd_pool, NULL);
2192 vkDestroyPipeline(demo->device, demo->pipeline, NULL);
2193 vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
2194 vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
2195 vkDestroyDescriptorSetLayout(demo->device, demo->desc_layout, NULL);
2197 vkDestroyBuffer(demo->device, demo->vertices.buf, NULL);
2198 vkFreeMemory(demo->device, demo->vertices.mem, NULL);
2200 for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
2201 vkDestroyImageView(demo->device, demo->textures[i].view, NULL);
2202 vkDestroyImage(demo->device, demo->textures[i].image, NULL);
2203 vkFreeMemory(demo->device, demo->textures[i].mem, NULL);
2204 vkDestroySampler(demo->device, demo->textures[i].sampler, NULL);
2207 for (i = 0; i < demo->swapchainImageCount; i++) {
2208 vkDestroyImageView(demo->device, demo->buffers[i].view, NULL);
2211 vkDestroyImageView(demo->device, demo->depth.view, NULL);
2212 vkDestroyImage(demo->device, demo->depth.image, NULL);
2213 vkFreeMemory(demo->device, demo->depth.mem, NULL);
2215 free(demo->buffers);
2217 // Second, re-perform the demo_prepare() function, which will re-create the
2222 int SDL_main(int argc, char *argv[])
2225 SDL_Surface* screenSurface = NULL;
2227 printf("Start ~~~~~~~~\n");
2228 argc_init(&demo, argc, argv);
2231 if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTS ) < 0 ) {
2232 printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
2235 SDL_GetDisplayMode(0, 0, &(demo.sdl_mode));
2237 demo.width = demo.sdl_mode.w;
2238 demo.height = demo.sdl_mode.h;
2239 demo.depthStencil = 1.0;
2240 demo.depthIncrement = -0.01f;
2242 printf("width %d, height %d\n",demo.sdl_mode.w,demo.sdl_mode.h);
2243 demo.sdl_window = SDL_CreateWindow( "SDL Vulkan Sample",
2244 0, 0, demo.sdl_mode.w, demo.sdl_mode.h,
2245 SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_VULKAN);
2246 if( demo.sdl_window == NULL ) {
2247 printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
2250 demo_init_vk(&demo);
2251 demo_init_vk_swapchain(&demo);
2252 demo_prepare(&demo);
2254 //screenSurface = SDL_GetWindowSurface( demo.sdl_window );
2259 while (SDL_PollEvent(&event))
2261 printf("SDL Event type :: %d\n",event.type);
2262 if (event.type == SDL_MOUSEBUTTONDOWN)
2264 printf("SDL_MOUSEBUTTONDOWN Event!!\n");
2267 if (event.type == SDL_MOUSEMOTION)
2269 printf("SDL_MOUSEMOTION Event!!\n");
2271 if(event.type == SDL_KEYDOWN)
2273 if(event.key.keysym.sym == 0)
2280 //Update the surface
2281 //SDL_UpdateWindowSurface( demo.sdl_window );
2283 //SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF ) );
2285 //Update the surface
2286 //SDL_UpdateWindowSurface( demo.sdl_window );
2288 demo_cleanup(&demo);
2290 SDL_DestroyWindow( demo.sdl_window );
2292 //Quit SDL subsystems