Skip to content

Instantly share code, notes, and snippets.

@aamedina
Last active October 31, 2023 02:26
Show Gist options
  • Save aamedina/34e2ac56c1e1a8d3256507057693bdd6 to your computer and use it in GitHub Desktop.
Save aamedina/34e2ac56c1e1a8d3256507057693bdd6 to your computer and use it in GitHub Desktop.
Drawing a Triangle with Vulkan in Clojure
;; Based on the 01_InitRaytracing.cpp example from VkRayTutorials
;; Copyright (c) 2018 Adrian Medina
(ns vk.ray.tutorials.init-raytracing
(:gen-class)
(:require
[vk.ray.tutorials.util :as util])
(:import
(java.nio ByteBuffer FloatBuffer IntBuffer LongBuffer)
(org.lwjgl PointerBuffer)
(org.lwjgl.system MemoryUtil)
(org.lwjgl.glfw GLFW GLFWVulkan)
(org.lwjgl.glfw GLFWKeyCallback GLFWKeyCallbackI
GLFWWindowSizeCallback GLFWWindowSizeCallbackI)
(org.lwjgl.vulkan EXTDebugReport KHRSwapchain KHRSurface VK11)
(org.lwjgl.vulkan VkApplicationInfo
VkAttachmentDescription
VkAttachmentReference
VkBufferCreateInfo
VkClearValue
VkCommandBuffer
VkCommandBufferAllocateInfo
VkCommandBufferBeginInfo
VkCommandPoolCreateInfo
VkDebugReportCallbackCreateInfoEXT
VkDebugReportCallbackEXT
VkDebugReportCallbackEXTI
VkDevice
VkDeviceCreateInfo
VkDeviceQueueCreateInfo
VkExtent2D
VkFramebufferCreateInfo
VkGraphicsPipelineCreateInfo
VkImageMemoryBarrier
VkImageViewCreateInfo
VkInstance
VkInstanceCreateInfo
VkMemoryAllocateInfo
VkMemoryRequirements
VkPhysicalDevice
VkPhysicalDeviceMemoryProperties
VkPipelineColorBlendAttachmentState
VkPipelineColorBlendStateCreateInfo
VkPipelineDepthStencilStateCreateInfo
VkPipelineDynamicStateCreateInfo
VkPipelineInputAssemblyStateCreateInfo
VkPipelineLayoutCreateInfo
VkPipelineMultisampleStateCreateInfo
VkPipelineRasterizationStateCreateInfo
VkPipelineShaderStageCreateInfo
VkPipelineVertexInputStateCreateInfo
VkPipelineViewportStateCreateInfo
VkPresentInfoKHR
VkQueue
VkQueueFamilyProperties
VkRect2D
VkRenderPassBeginInfo
VkRenderPassCreateInfo
VkSemaphoreCreateInfo
VkShaderModuleCreateInfo
VkSubmitInfo
VkSubpassDescription
VkSurfaceFormatKHR
VkSurfaceCapabilitiesKHR
VkSwapchainCreateInfoKHR
VkVertexInputAttributeDescription
VkVertexInputBindingDescription
VkViewport)))
(def ^:private validation?
(Boolean/parseBoolean (System/getProperty "vulkan.validation" "false")))
(def ^:private layers
(into-array ByteBuffer [(util/utf8 "A validation layer found an error.")]))
(def ^:private ^:const vk-flags-none 0)
(def ^:private ^:const uint64-max -1)
(defonce ^:private resources
(atom {:must-recreate? true
:swapchain nil
:framebuffers nil
:width 800
:height 600
:render-command-buffers nil
:setup-command-buffer nil
:color-format-and-space nil
:command-pool nil
:post-present-command-buffer nil
:queue nil
:render-pass nil
:render-command-pool nil
:vertices nil
:pipeline nil
:physical-device nil}))
(defn- ^VkInstance create-instance
[^PointerBuffer required-extensions]
(let [app-info (.. (VkApplicationInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_APPLICATION_INFO)
(pApplicationName (util/utf8 "GLFW Vulkan Demo"))
(pEngineName (util/utf8 ""))
(apiVersion (VK11/VK_MAKE_VERSION 1 1 85)))
ptr (MemoryUtil/memAllocPointer (inc (.remaining required-extensions)))
pp-enabled-extension-names (doto ptr
(.put required-extensions))
vk-ext-debug-report-ext (util/utf8 EXTDebugReport/VK_EXT_DEBUG_REPORT_EXTENSION_NAME)
pp-enabled-extension-names (doto pp-enabled-extension-names
(.put vk-ext-debug-report-ext)
(.flip))
ptr (MemoryUtil/memAllocPointer (alength layers))
_ (when validation?
(dotimes [i (alength layers)]
(.put ptr (aget layers i))))
pp-enabled-layer-names (doto ptr
(.flip))
p-create-info (.. (VkInstanceCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO)
(pNext 0)
(pApplicationInfo app-info)
(ppEnabledExtensionNames pp-enabled-extension-names)
(ppEnabledLayerNames pp-enabled-layer-names))
p-instance (MemoryUtil/memAllocPointer 1)
err (VK11/vkCreateInstance p-create-info nil p-instance)
instance (.get p-instance 0)
_ (assert (= err VK11/VK_SUCCESS)
(str "Failed to create VkInstance: " (util/error-msg err)))
_ (MemoryUtil/memFree p-instance)
instance (VkInstance. instance p-create-info)
_ (.free p-create-info)
_ (MemoryUtil/memFree pp-enabled-layer-names)
_ (MemoryUtil/memFree pp-enabled-extension-names)
_ (MemoryUtil/memFree (.pApplicationName app-info))
_ (MemoryUtil/memFree (.pEngineName app-info))
_ (.free app-info)]
instance))
(defn- setup-debugging
[instance flags callback]
(let [dbg-create-info (.. (VkDebugReportCallbackCreateInfoEXT/calloc)
(sType EXTDebugReport/VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT)
(pNext 0)
(pfnCallback callback)
(pUserData 0)
(flags flags))
p-callback (MemoryUtil/memAllocLong 1)
err (EXTDebugReport/vkCreateDebugReportCallbackEXT instance
dbg-create-info
nil
p-callback)
callback-handle (.get p-callback 0)
_ (MemoryUtil/memFree p-callback)
_ (.free dbg-create-info)]
(assert (= err VK11/VK_SUCCESS)
(str "Failed to create VkInstance: " (util/error-msg err)))
callback-handle))
(defn get-first-physical-device
[instance]
(let [p-physical-device-count (MemoryUtil/memAllocInt 1)
err (VK11/vkEnumeratePhysicalDevices instance
p-physical-device-count
nil)
_ (assert (= err VK11/VK_SUCCESS)
(str "Failed to get number of physical devices: "
(util/error-msg err)))
physical-device-count (.get p-physical-device-count 0)
p-physical-devices (MemoryUtil/memAllocPointer physical-device-count)
err (VK11/vkEnumeratePhysicalDevices instance
p-physical-device-count
p-physical-devices)
physical-device (.get p-physical-devices 0)
_ (MemoryUtil/memFree p-physical-device-count)
_ (MemoryUtil/memFree p-physical-devices)]
(assert (= err VK11/VK_SUCCESS)
(str "Failed to get physical devices: " (util/error-msg err)))
(VkPhysicalDevice. physical-device instance)))
(defn- create-device-and-get-graphics-queue-family
[physical-device]
(let [p-queue-fam-prop-count
(MemoryUtil/memAllocInt 1)
_
(VK11/vkGetPhysicalDeviceQueueFamilyProperties physical-device
p-queue-fam-prop-count
nil)
queue-count
(.get p-queue-fam-prop-count 0)
queue-props
(VkQueueFamilyProperties/calloc queue-count)
_
(VK11/vkGetPhysicalDeviceQueueFamilyProperties physical-device
p-queue-fam-prop-count
queue-props)
_
(MemoryUtil/memFree p-queue-fam-prop-count)
graphics-queue-family-index
(loop [i 0]
(if (< i queue-count)
(if (not (zero? (bit-and (.queueFlags (.get queue-props i))
VK11/VK_QUEUE_GRAPHICS_BIT)))
i
(recur (inc i)))
i))
_ (.free queue-props)
p-queue-priorities
(doto (MemoryUtil/memAllocFloat 1)
(.put 0.0)
(.flip))
queue-create-info
(.. (VkDeviceQueueCreateInfo/calloc 1)
(sType VK11/VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
(queueFamilyIndex graphics-queue-family-index)
(pQueuePriorities p-queue-priorities))
vk-khr-swapchain-extension
(util/utf8 KHRSwapchain/VK_KHR_SWAPCHAIN_EXTENSION_NAME)
extensions
(doto (MemoryUtil/memAllocPointer 1)
(.put vk-khr-swapchain-extension)
(.flip))
pp-enabled-layer-names
(MemoryUtil/memAllocPointer (alength layers))
_
(when validation?
(dotimes [i (alength layers)]
(.put pp-enabled-layer-names (aget layers i))))
_
(.flip pp-enabled-layer-names)
device-create-info
(.. (VkDeviceCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
(pNext 0)
(pQueueCreateInfos queue-create-info)
(ppEnabledExtensionNames extensions)
(ppEnabledLayerNames pp-enabled-layer-names))
p-device (MemoryUtil/memAllocPointer 1)
err
(VK11/vkCreateDevice physical-device
device-create-info
nil
p-device)
device
(.get p-device 0)
_ (MemoryUtil/memFree p-device)
_ (assert (= err VK11/VK_SUCCESS)
(str "Failed to create device: " (util/error-msg err)))
memory-properties (VkPhysicalDeviceMemoryProperties/calloc)
_ (VK11/vkGetPhysicalDeviceMemoryProperties physical-device
memory-properties)]
(try
{:device (VkDevice. device physical-device device-create-info)
:queue-family-index graphics-queue-family-index
:memory-properties memory-properties}
(finally
(.free device-create-info)
(MemoryUtil/memFree pp-enabled-layer-names)
(MemoryUtil/memFree vk-khr-swapchain-extension)
(MemoryUtil/memFree extensions)
(MemoryUtil/memFree p-queue-priorities)))))
(defn- get-color-format-and-space
[physical-device surface]
(let [p-queue-family-prop-count (MemoryUtil/memAllocInt 1)
_
(VK11/vkGetPhysicalDeviceQueueFamilyProperties physical-device
p-queue-family-prop-count
nil)
queue-count (.get p-queue-family-prop-count 0)
queue-props (VkQueueFamilyProperties/calloc queue-count)
_
(VK11/vkGetPhysicalDeviceQueueFamilyProperties physical-device
p-queue-family-prop-count
queue-props)
_ (MemoryUtil/memFree p-queue-family-prop-count)
supports-present (MemoryUtil/memAllocInt queue-count)
_
(dotimes [i queue-count]
(.position supports-present i)
(let [err (KHRSurface/vkGetPhysicalDeviceSurfaceSupportKHR
physical-device i surface supports-present)]
(util/assert-vk-success
err
"Physical device does not support KHR surfaces: ")))
[graphics-queue-node-index present-queue-node-index]
(loop [graphics-queue-node-index Integer/MAX_VALUE
present-queue-node-index Integer/MAX_VALUE
i 0]
(if (< i queue-count)
(if (not (zero? (bit-and (.queueFlags (.get queue-props i))
VK11/VK_QUEUE_GRAPHICS_BIT)))
(cond
(== graphics-queue-node-index Integer/MAX_VALUE)
(recur i present-queue-node-index (inc i))
(== (.get supports-present i) VK11/VK_TRUE)
[i i]
:else (recur graphics-queue-node-index
present-queue-node-index
(inc i)))
(recur graphics-queue-node-index
present-queue-node-index
(inc i)))
[graphics-queue-node-index
(if (== present-queue-node-index Integer/MAX_VALUE)
(reduce (fn [present-queue-node-index i]
(if (== (.get supports-present i) VK11/VK_TRUE)
(reduced i)
present-queue-node-index))
present-queue-node-index (range queue-count))
present-queue-node-index)]))
_ (.free queue-props)
_ (MemoryUtil/memFree supports-present)
_ (assert (not (== graphics-queue-node-index Integer/MAX_VALUE))
"No graphics queue found.")
_ (assert (not (== present-queue-node-index Integer/MAX_VALUE))
"No presentation queue found.")
_ (assert (== graphics-queue-node-index present-queue-node-index)
"Presentation queue != graphics queue")
p-format-count (MemoryUtil/memAllocInt 1)
err (KHRSurface/vkGetPhysicalDeviceSurfaceFormatsKHR physical-device
surface
p-format-count
nil)
format-count (.get p-format-count 0)
_ (assert (= err VK11/VK_SUCCESS)
(str "Failed to query physical device surface formats: "
(util/error-msg err)))
surface-formats (VkSurfaceFormatKHR/calloc format-count)
err (KHRSurface/vkGetPhysicalDeviceSurfaceFormatsKHR physical-device
surface
p-format-count
surface-formats)
_ (assert (= err VK11/VK_SUCCESS)
(str "Failed to query physical device surface formats: "
(util/error-msg err)))
color-format (if (and (== format-count 1)
(== (.format (.get surface-formats 0))
VK11/VK_FORMAT_UNDEFINED))
VK11/VK_FORMAT_B8G8R8A8_UNORM
(.format (.get surface-formats 0)))
color-space (.colorSpace (.get surface-formats 0))
_ (.free surface-formats)]
{:color-format color-format
:color-space color-space}))
(defn- create-command-pool
[device queue-node-index]
(let [command-pool-info (.. (VkCommandPoolCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO)
(queueFamilyIndex queue-node-index)
(flags VK11/VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT))
p-cmd-pool (MemoryUtil/memAllocLong 1)
err (VK11/vkCreateCommandPool device command-pool-info nil p-cmd-pool)
command-pool (.get p-cmd-pool 0)]
(.free command-pool-info)
(MemoryUtil/memFree p-cmd-pool)
(assert (== err VK11/VK_SUCCESS)
(str "Failed to create command pool: " (util/error-msg err)))
command-pool))
(defn- create-device-queue
[device queue-family-index]
(let [p-queue (MemoryUtil/memAllocPointer 1)
_ (VK11/vkGetDeviceQueue device queue-family-index 0 p-queue)
queue (.get p-queue 0)]
(MemoryUtil/memFree p-queue)
(VkQueue. queue device)))
(defn- create-command-buffer
[device command-pool]
(let [cmd-buf-allocate-info (.. (VkCommandBufferAllocateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO)
(commandPool command-pool)
(level VK11/VK_COMMAND_BUFFER_LEVEL_PRIMARY)
(commandBufferCount 1))
p-command-buffer (MemoryUtil/memAllocPointer 1)
err (VK11/vkAllocateCommandBuffers device
cmd-buf-allocate-info
p-command-buffer)
_ (.free cmd-buf-allocate-info)
command-buffer (.get p-command-buffer 0)
_ (MemoryUtil/memFree p-command-buffer)]
(assert (== err VK11/VK_SUCCESS)
(str "Failed to allocate command buffer: " (util/error-msg err)))
(VkCommandBuffer. command-buffer device)))
(defn- image-barrier
[cmd-buf img aspect-mask old-img-layout src-access new-img-layout dst-access]
(let [img-mem-barrier (.. (VkImageMemoryBarrier/calloc 1)
(sType VK11/VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER)
(pNext 0)
(oldLayout old-img-layout)
(srcAccessMask src-access)
(newLayout new-img-layout)
(dstAccessMask dst-access)
(srcQueueFamilyIndex VK11/VK_QUEUE_FAMILY_IGNORED)
(dstQueueFamilyIndex VK11/VK_QUEUE_FAMILY_IGNORED)
(image img))
_ (.. (.subresourceRange img-mem-barrier)
(aspectMask aspect-mask)
(baseMipLevel 0)
(levelCount 1)
(layerCount 1))
src-stage-flags VK11/VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
dst-stage-flags VK11/VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT]
(VK11/vkCmdPipelineBarrier cmd-buf src-stage-flags dst-stage-flags
vk-flags-none nil nil img-mem-barrier)
(.free img-mem-barrier)))
(defn- create-swapchain
[device physical-device surface old-swapchain command-buffer
new-width new-height color-format color-space]
(let [surface-caps (VkSurfaceCapabilitiesKHR/calloc)
err (KHRSurface/vkGetPhysicalDeviceSurfaceCapabilitiesKHR
physical-device surface surface-caps)
_ (assert (== err VK11/VK_SUCCESS)
(str "Failed to get physical device surface capabilities: "
(util/error-msg err)))
p-present-mode-count (MemoryUtil/memAllocInt 1)
err (KHRSurface/vkGetPhysicalDeviceSurfacePresentModesKHR
physical-device surface p-present-mode-count nil)
present-mode-count (.get p-present-mode-count 0)
_ (assert (== err VK11/VK_SUCCESS)
(str "Failed to get number of physical device surface presentation modes: "
(util/error-msg err)))
p-present-modes (MemoryUtil/memAllocInt present-mode-count)
err (KHRSurface/vkGetPhysicalDeviceSurfacePresentModesKHR
physical-device surface p-present-mode-count p-present-modes)
_ (MemoryUtil/memFree p-present-mode-count)
_ (assert (== err VK11/VK_SUCCESS)
(str "Failed to get physical device surface presentation modes: "
(util/error-msg err)))
swapchain-present-mode
(loop [swapchain-present-mode KHRSurface/VK_PRESENT_MODE_FIFO_KHR
i 0]
(if (< i present-mode-count)
(if (== (.get p-present-modes i)
KHRSurface/VK_PRESENT_MODE_MAILBOX_KHR)
KHRSurface/VK_PRESENT_MODE_MAILBOX_KHR
(recur (if (and (not (== swapchain-present-mode
KHRSurface/VK_PRESENT_MODE_MAILBOX_KHR))
(== (.get p-present-modes i)
KHRSurface/VK_PRESENT_MODE_IMMEDIATE_KHR))
KHRSurface/VK_PRESENT_MODE_IMMEDIATE_KHR
swapchain-present-mode)
(inc i)))
swapchain-present-mode))
_ (MemoryUtil/memFree p-present-modes)
desired-number-of-swapchain-images
(as-> (inc (.minImageCount surface-caps)) n
(if (and (pos? (.maxImageCount surface-caps))
(> n (.maxImageCount surface-caps)))
(.maxImageCount surface-caps)
n))
current-extent (.currentExtent surface-caps)
current-width (.width current-extent)
current-height (.height current-extent)
width (if (pos? current-width)
current-width
new-width)
height (if (pos? current-height)
current-height
new-height)
pre-transform (if (not (zero? (bit-and (.supportedTransforms surface-caps)
KHRSurface/VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)))
KHRSurface/VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
(.currentTransform surface-caps))
_ (.free surface-caps)
swapchain-ci (.. (VkSwapchainCreateInfoKHR/calloc)
(sType KHRSwapchain/VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR)
(pNext 0)
(surface surface)
(minImageCount desired-number-of-swapchain-images)
(imageFormat color-format)
(imageColorSpace color-space)
(imageUsage VK11/VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
(preTransform pre-transform)
(imageArrayLayers 1)
(imageSharingMode VK11/VK_SHARING_MODE_EXCLUSIVE)
(pQueueFamilyIndices nil)
(presentMode swapchain-present-mode)
(oldSwapchain old-swapchain)
(clipped true)
(compositeAlpha KHRSurface/VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR))
_ (.. (.imageExtent swapchain-ci)
(width width)
(height height))
p-swapchain (MemoryUtil/memAllocLong 1)
err (KHRSwapchain/vkCreateSwapchainKHR device
swapchain-ci
nil
p-swapchain)
_ (.free swapchain-ci)
swapchain (.get p-swapchain 0)
_ (MemoryUtil/memFree p-swapchain)
_ (assert (== err VK11/VK_SUCCESS)
(str "Failed to create swapchain: " (util/error-msg err)))
_ (when-not (== old-swapchain VK11/VK_NULL_HANDLE)
(KHRSwapchain/vkDestroySwapchainKHR device old-swapchain nil))
p-image-count (MemoryUtil/memAllocInt 1)
err (KHRSwapchain/vkGetSwapchainImagesKHR device
swapchain
p-image-count
nil)
image-count (.get p-image-count 0)
_ (assert (== err VK11/VK_SUCCESS)
(str "Failed to get number of swapchain images: "
(util/error-msg err)))
p-swapchain-images (MemoryUtil/memAllocLong image-count)
err (KHRSwapchain/vkGetSwapchainImagesKHR device
swapchain
p-image-count
p-swapchain-images)
_ (assert (== err VK11/VK_SUCCESS)
(str "Failed to get swapchain images: " (util/error-msg err)))
_ (MemoryUtil/memFree p-image-count)
images (long-array image-count)
image-views (long-array image-count)
p-buffer-view (MemoryUtil/memAllocLong 1)
color-attachment-view (.. (VkImageViewCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO)
(pNext 0)
(format color-format)
(viewType VK11/VK_IMAGE_VIEW_TYPE_2D)
(flags vk-flags-none))
_ (.. (.components color-attachment-view)
(r VK11/VK_COMPONENT_SWIZZLE_R)
(g VK11/VK_COMPONENT_SWIZZLE_G)
(b VK11/VK_COMPONENT_SWIZZLE_B)
(a VK11/VK_COMPONENT_SWIZZLE_A))
_ (.. (.subresourceRange color-attachment-view)
(aspectMask VK11/VK_IMAGE_ASPECT_COLOR_BIT)
(baseMipLevel 0)
(levelCount 1)
(baseArrayLayer 0)
(layerCount 1))]
(dotimes [i image-count]
(aset images i (.get p-swapchain-images i))
(image-barrier command-buffer
(aget images i)
VK11/VK_IMAGE_ASPECT_COLOR_BIT
VK11/VK_IMAGE_LAYOUT_UNDEFINED
0
VK11/VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
VK11/VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
(.image color-attachment-view (aget images i))
(let [err (VK11/vkCreateImageView device
color-attachment-view
nil
p-buffer-view)]
(aset image-views i (.get p-buffer-view 0))
(assert (== err VK11/VK_SUCCESS)
(str "Failed to create image view: " (util/error-msg err)))))
(.free color-attachment-view)
(MemoryUtil/memFree p-buffer-view)
(MemoryUtil/memFree p-swapchain-images)
{:images images
:image-views image-views
:swapchain-handle swapchain}))
(defn- create-render-pass
[device color-format]
(let [attachments (.. (VkAttachmentDescription/calloc 1)
(format color-format)
(samples VK11/VK_SAMPLE_COUNT_1_BIT)
(loadOp VK11/VK_ATTACHMENT_LOAD_OP_CLEAR)
(storeOp VK11/VK_ATTACHMENT_STORE_OP_STORE)
(stencilLoadOp VK11/VK_ATTACHMENT_LOAD_OP_DONT_CARE)
(stencilStoreOp VK11/VK_ATTACHMENT_STORE_OP_DONT_CARE)
(initialLayout VK11/VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
(finalLayout VK11/VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL))
color-ref (.. (VkAttachmentReference/calloc 1)
(attachment 0)
(layout VK11/VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL))
subpass (.. (VkSubpassDescription/calloc 1)
(pipelineBindPoint VK11/VK_PIPELINE_BIND_POINT_GRAPHICS)
(flags vk-flags-none)
(pInputAttachments nil)
(colorAttachmentCount (.remaining color-ref))
(pColorAttachments color-ref)
(pResolveAttachments nil)
(pDepthStencilAttachment nil)
(pPreserveAttachments nil))
render-pass-info (.. (VkRenderPassCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO)
(pNext 0)
(pAttachments attachments)
(pSubpasses subpass)
(pDependencies nil))
p-render-pass (MemoryUtil/memAllocLong 1)
err (VK11/vkCreateRenderPass device render-pass-info nil p-render-pass)
render-pass (.get p-render-pass 0)]
(MemoryUtil/memFree p-render-pass)
(.free render-pass-info)
(.free color-ref)
(.free subpass)
(.free attachments)
(assert (== err VK11/VK_SUCCESS)
(str "Failed to create clear render pass: " (util/error-msg err)))
render-pass))
(defn- create-framebuffers
[device swapchain render-pass width height]
(let [attachments (MemoryUtil/memAllocLong 1)
fci (.. (VkFramebufferCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO)
(pAttachments attachments)
(flags vk-flags-none)
(height height)
(width width)
(layers 1)
(pNext 0)
(renderPass render-pass))
framebuffers (long-array (alength (:images swapchain)))
p-framebuffer (MemoryUtil/memAllocLong 1)]
(dotimes [i (alength (:images swapchain))]
(.put attachments 0 (aget (:image-views swapchain) i))
(let [err (VK11/vkCreateFramebuffer device fci nil p-framebuffer)
framebuffer (.get p-framebuffer 0)]
(assert (== err VK11/VK_SUCCESS)
(str "Failed to create framebuffer: " (util/error-msg err)))
(aset framebuffers i framebuffer)))
(MemoryUtil/memFree attachments)
(MemoryUtil/memFree p-framebuffer)
(.free fci)
framebuffers))
(defn- submit-command-buffer
[queue command-buffer]
(when (and command-buffer (.address command-buffer))
(let [submit-info (.. (VkSubmitInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_SUBMIT_INFO))
p-command-buffers (doto (MemoryUtil/memAllocPointer 1)
(.put command-buffer)
(.flip))
_ (.pCommandBuffers submit-info p-command-buffers)
err (VK11/vkQueueSubmit queue submit-info VK11/VK_NULL_HANDLE)]
(MemoryUtil/memFree p-command-buffers)
(.free submit-info)
(util/assert-vk-success err "Failed to submit command buffer"))))
(defn- resize-buffer
[buffer new-capacity]
(let [new-buffer (org.lwjgl.BufferUtils/createByteBuffer new-capacity)]
(.flip buffer)
(.put new-buffer buffer)
new-buffer))
(defn- ^ByteBuffer io-resource-to-byte-buffer
[resource buffer-size]
(let [url (clojure.java.io/resource resource)
file (clojure.java.io/as-file (.getFile url))]
(if (.isFile file)
(with-open [fis (java.io.FileInputStream. file)
fc (.getChannel fis)]
(.map fc java.nio.channels.FileChannel$MapMode/READ_ONLY 0 (.size fc)))
(with-open [source (.openStream url)]
(when (nil? source)
(throw (java.io.FileNotFoundException. resource)))
(with-open [rbc (java.nio.channels.Channels/newChannel source)]
(loop [buffer (org.lwjgl.BufferUtils/createByteBuffer buffer-size)]
(let [bytes (.read rbc buffer)]
(if-not (== bytes -1)
(do
(.flip buffer)
buffer)
(if (zero? (.remaining buffer))
(recur (resize-buffer buffer (* (.capacity buffer) 2)))
(recur buffer))))))))))
(defn- load-shader
([device resource]
(let [shader-code (io-resource-to-byte-buffer resource 1024)
module-create-info (.. (VkShaderModuleCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO)
(pNext 0)
(pCode shader-code)
(flags 0))
p-shader-module (MemoryUtil/memAllocLong 1)
err (VK11/vkCreateShaderModule device
module-create-info
nil
p-shader-module)
shader-module (.get p-shader-module 0)
_ (MemoryUtil/memFree p-shader-module)]
(util/assert-vk-success err "Failed to create shader module")
shader-module))
([device resource stage]
(.. (VkPipelineShaderStageCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO)
(stage stage)
(module (load-shader device resource))
(pName (util/utf8 "main")))))
(defn- get-memory-type
[device-memory-props type-bits props type-index]
(loop [bits type-bits
i 0]
(if (< i 32)
(if (== (bit-and bits 1) 1)
(if (== (bit-and (.propertyFlags (.memoryTypes device-memory-props i))
props)
props)
(do
(.put type-index 0 i)
true)
(recur (bit-shift-right bits 1) (inc i)))
(recur (bit-shift-right bits 1) (inc i)))
false)))
(defn- create-vertices
[device-memory-props device]
(let [vertex-buffer (MemoryUtil/memAlloc (* 3 2 4))
fb (doto (.asFloatBuffer vertex-buffer)
(.put -0.5)
(.put -0.5)
(.put 0.5)
(.put -0.5)
(.put 0.0)
(.put 0.5))
mem-alloc (.. (VkMemoryAllocateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO)
(pNext 0)
(allocationSize 0)
(memoryTypeIndex 0))
mem-reqs (VkMemoryRequirements/calloc)
buf-info (.. (VkBufferCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO)
(pNext 0)
(size (.remaining vertex-buffer))
(usage VK11/VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
(flags 0))
p-buffer (MemoryUtil/memAllocLong 1)
err (VK11/vkCreateBuffer device buf-info nil p-buffer)
vertices-buf (.get p-buffer 0)
_ (MemoryUtil/memFree p-buffer)
_ (.free buf-info)
_ (util/assert-vk-success err "Failed to create vertex buffer")
_ (VK11/vkGetBufferMemoryRequirements device vertices-buf mem-reqs)
_ (.allocationSize mem-alloc (.size mem-reqs))
memory-type-index (MemoryUtil/memAllocInt 1)
_ (get-memory-type device-memory-props
(.memoryTypeBits mem-reqs)
VK11/VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
memory-type-index)
_ (.memoryTypeIndex mem-alloc (.get memory-type-index 0))
_ (MemoryUtil/memFree memory-type-index)
_ (.free mem-reqs)
p-memory (MemoryUtil/memAllocLong 1)
err (VK11/vkAllocateMemory device mem-alloc nil p-memory)
vertices-mem (.get p-memory 0)
_ (MemoryUtil/memFree p-memory)
_ (util/assert-vk-success err "Failed to allocate vertex memory")
p-data (MemoryUtil/memAllocPointer 1)
err (VK11/vkMapMemory device vertices-mem 0 (.allocationSize mem-alloc)
0 p-data)
_ (.free mem-alloc)
data (.get p-data 0)
_ (MemoryUtil/memFree p-data)
_ (util/assert-vk-success err "Failed to map vertex memory")
_ (MemoryUtil/memCopy (MemoryUtil/memAddress vertex-buffer)
data
(.remaining vertex-buffer))
_ (MemoryUtil/memFree vertex-buffer)
_ (VK11/vkUnmapMemory device vertices-mem)
err (VK11/vkBindBufferMemory device vertices-buf vertices-mem 0)
_ (util/assert-vk-success err "Failed to bind memory to vertex buffer")
binding-desc (.. (VkVertexInputBindingDescription/calloc 1)
(binding 0)
(stride (* 2 4))
(inputRate VK11/VK_VERTEX_INPUT_RATE_VERTEX))
attr-desc (.. (VkVertexInputAttributeDescription/calloc 1)
(binding 0)
(location 0)
(format VK11/VK_FORMAT_R32G32_SFLOAT)
(offset 0))
vi (.. (VkPipelineVertexInputStateCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO)
(pNext 0)
(pVertexBindingDescriptions binding-desc)
(pVertexAttributeDescriptions attr-desc))]
{:create-info vi
:vertex-buffer vertices-buf}))
(defn- create-pipeline
[device render-pass vi]
(let [input-assembly-state
(.. (VkPipelineInputAssemblyStateCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO)
(topology VK11/VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST))
rasterization-state
(.. (VkPipelineRasterizationStateCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO)
(polygonMode VK11/VK_POLYGON_MODE_FILL)
(cullMode VK11/VK_CULL_MODE_NONE)
(frontFace VK11/VK_FRONT_FACE_COUNTER_CLOCKWISE)
(depthClampEnable false)
(rasterizerDiscardEnable false)
(depthBiasEnable false))
color-write-mask
(.. (VkPipelineColorBlendAttachmentState/calloc 1)
(blendEnable false)
(colorWriteMask 0xf))
color-blend-state
(.. (VkPipelineColorBlendStateCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO)
(pAttachments color-write-mask))
viewport-state
(.. (VkPipelineViewportStateCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO)
(viewportCount 1)
(scissorCount 1))
p-dynamic-states
(doto (MemoryUtil/memAllocInt 2)
(.put VK11/VK_DYNAMIC_STATE_VIEWPORT)
(.put VK11/VK_DYNAMIC_STATE_SCISSOR)
(.flip))
dynamic-state (.. (VkPipelineDynamicStateCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO)
(pDynamicStates p-dynamic-states))
depth-stencil-state (.. (VkPipelineDepthStencilStateCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO)
(depthTestEnable false)
(depthWriteEnable false)
(depthCompareOp VK11/VK_COMPARE_OP_ALWAYS)
(depthBoundsTestEnable false)
(stencilTestEnable false))
_ (.. (.back depth-stencil-state)
(failOp VK11/VK_STENCIL_OP_KEEP)
(passOp VK11/VK_STENCIL_OP_KEEP)
(compareOp VK11/VK_COMPARE_OP_ALWAYS))
_ (.front depth-stencil-state (.back depth-stencil-state))
multisample-state (.. (VkPipelineMultisampleStateCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO)
(pSampleMask nil)
(rasterizationSamples VK11/VK_SAMPLE_COUNT_1_BIT))
shader-stages (VkPipelineShaderStageCreateInfo/calloc 2)
vertex-shader (load-shader device
"vk/ray/tutorials/shaders/triangle.vert.spv"
VK11/VK_SHADER_STAGE_VERTEX_BIT)
_ (.set (.get shader-stages 0) vertex-shader)
fragment-shader (load-shader device
"vk/ray/tutorials/shaders/triangle.frag.spv"
VK11/VK_SHADER_STAGE_FRAGMENT_BIT)
_ (.set (.get shader-stages 1) fragment-shader)
p-pipeline-layout-create-info (.. (VkPipelineLayoutCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO)
(pNext 0)
(pSetLayouts nil))
p-pipeline-layout (MemoryUtil/memAllocLong 1)
err (VK11/vkCreatePipelineLayout device
p-pipeline-layout-create-info
nil
p-pipeline-layout)
layout (.get p-pipeline-layout 0)
_ (MemoryUtil/memFree p-pipeline-layout)
_ (.free p-pipeline-layout-create-info)
_ (util/assert-vk-success err "Failed to create pipeline layout")
pipeline-create-info (.. (VkGraphicsPipelineCreateInfo/calloc 1)
(sType VK11/VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO)
(layout layout)
(renderPass render-pass)
(pVertexInputState vi)
(pInputAssemblyState input-assembly-state)
(pRasterizationState rasterization-state)
(pColorBlendState color-blend-state)
(pMultisampleState multisample-state)
(pViewportState viewport-state)
(pDepthStencilState depth-stencil-state)
(pStages shader-stages)
(pDynamicState dynamic-state))
p-pipelines (MemoryUtil/memAllocLong 1)
err (VK11/vkCreateGraphicsPipelines device
VK11/VK_NULL_HANDLE
pipeline-create-info
nil
p-pipelines)
pipeline (.get p-pipelines 0)]
(.free shader-stages)
(.free multisample-state)
(.free depth-stencil-state)
(.free dynamic-state)
(MemoryUtil/memFree p-dynamic-states)
(.free viewport-state)
(.free color-blend-state)
(.free color-write-mask)
(.free rasterization-state)
(.free input-assembly-state)
(util/assert-vk-success err "Failed to create pipeline")
pipeline))
(defn- create-pre-present-barrier
[present-image]
(let [image-memory-barrier (.. (VkImageMemoryBarrier/calloc 1)
(sType VK11/VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER)
(pNext 0)
(srcAccessMask VK11/VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
(dstAccessMask 0)
(oldLayout VK11/VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
(newLayout KHRSwapchain/VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
(srcQueueFamilyIndex VK11/VK_QUEUE_FAMILY_IGNORED)
(dstQueueFamilyIndex VK11/VK_QUEUE_FAMILY_IGNORED))]
(.. (.subresourceRange image-memory-barrier)
(aspectMask VK11/VK_IMAGE_ASPECT_COLOR_BIT)
(baseMipLevel 0)
(levelCount 1)
(baseArrayLayer 0)
(layerCount 1))
(.image image-memory-barrier present-image)
image-memory-barrier))
(defn- create-render-command-buffers
[device command-pool framebuffers render-pass width height pipeline vertices swapchain]
(let [cmd-buf-allocate-info (.. (VkCommandBufferAllocateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO)
(commandPool command-pool)
(level VK11/VK_COMMAND_BUFFER_LEVEL_PRIMARY)
(commandBufferCount (alength framebuffers)))
p-command-buffer (MemoryUtil/memAllocPointer (alength framebuffers))
err (VK11/vkAllocateCommandBuffers device
cmd-buf-allocate-info
p-command-buffer)
_ (util/assert-vk-success err "Failed to allocate render command buffer")
render-command-buffers (make-array VkCommandBuffer
(alength framebuffers))
_ (dotimes [i (alength framebuffers)]
(aset render-command-buffers i (VkCommandBuffer. (.get p-command-buffer i)
device)))
_ (MemoryUtil/memFree p-command-buffer)
_ (.free cmd-buf-allocate-info)
cmd-buf-info (.. (VkCommandBufferBeginInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO)
(pNext 0))
clear-values (VkClearValue/calloc 1)
_ (doto (.color clear-values)
(.float32 0 (/ 100.0 255.0))
(.float32 1 (/ 149.0 255.0))
(.float32 2 (/ 237.0 255.0))
(.float32 3 1.0))
render-pass-begin-info (.. (VkRenderPassBeginInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO)
(pNext 0)
(renderPass render-pass)
(pClearValues clear-values))
render-area (.renderArea render-pass-begin-info)
_ (doto (.offset render-area) (.set 0 0))
_ (doto (.extent render-area) (.set width height))]
(dotimes [i (alength render-command-buffers)]
(.framebuffer render-pass-begin-info (aget framebuffers i))
(let [render-command-buffer (aget render-command-buffers i)
err (VK11/vkBeginCommandBuffer render-command-buffer cmd-buf-info)
_ (util/assert-vk-success err "Failed to begin render command buffer")
_ (VK11/vkCmdBeginRenderPass render-command-buffer
render-pass-begin-info
VK11/VK_SUBPASS_CONTENTS_INLINE)
viewport (.. (VkViewport/calloc 1)
(height height)
(width width)
(minDepth 0.0)
(maxDepth 1.0))
_ (VK11/vkCmdSetViewport render-command-buffer 0 viewport)
_ (.free viewport)
scissor (VkRect2D/calloc 1)
_ (doto (.extent scissor) (.set width height))
_ (doto (.offset scissor) (.set 0 0))
_ (VK11/vkCmdSetScissor render-command-buffer 0 scissor)
_ (.free scissor)
_ (VK11/vkCmdBindPipeline render-command-buffer
VK11/VK_PIPELINE_BIND_POINT_GRAPHICS
pipeline)
offsets (doto (MemoryUtil/memAllocLong 1)
(.put 0 0))
p-buffers (doto (MemoryUtil/memAllocLong 1)
(.put 0 vertices))
_ (VK11/vkCmdBindVertexBuffers render-command-buffer
0
p-buffers
offsets)
_ (MemoryUtil/memFree p-buffers)
_ (MemoryUtil/memFree offsets)
_ (do
(VK11/vkCmdDraw render-command-buffer 3 1 0 0)
(VK11/vkCmdEndRenderPass render-command-buffer))
swapchain (aget (:images swapchain) i)
pre-present-barrier (create-pre-present-barrier swapchain)
_ (VK11/vkCmdPipelineBarrier render-command-buffer
VK11/VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
VK11/VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
vk-flags-none
nil
nil
pre-present-barrier)
_ (.free pre-present-barrier)
err (VK11/vkEndCommandBuffer render-command-buffer)]
(util/assert-vk-success err "Failed to begin render command buffer")))
(.free render-pass-begin-info)
(.free clear-values)
(.free cmd-buf-info)
render-command-buffers))
(defn create-post-present-barrier
[present-image]
(let [image-memory-barrier (.. (VkImageMemoryBarrier/calloc 1)
(sType VK11/VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER)
(pNext 0)
(srcAccessMask 0)
(dstAccessMask VK11/VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
(oldLayout KHRSwapchain/VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
(newLayout VK11/VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
(srcQueueFamilyIndex VK11/VK_QUEUE_FAMILY_IGNORED)
(dstQueueFamilyIndex VK11/VK_QUEUE_FAMILY_IGNORED))]
(.. (.subresourceRange image-memory-barrier)
(aspectMask VK11/VK_IMAGE_ASPECT_COLOR_BIT)
(baseMipLevel 0)
(levelCount 1)
(baseArrayLayer 0)
(layerCount 1))
(.image image-memory-barrier present-image)
image-memory-barrier))
(defn submit-post-present-barrier
[image command-buffer queue]
(let [cmd-buf-info (.. (VkCommandBufferBeginInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO)
(pNext 0))
err (VK11/vkBeginCommandBuffer command-buffer cmd-buf-info)
_ (.free cmd-buf-info)
_ (util/assert-vk-success err "Failed to begin command buffer")
post-present-barrier (create-post-present-barrier image)
_ (VK11/vkCmdPipelineBarrier command-buffer
VK11/VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
VK11/VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
vk-flags-none
nil
nil
post-present-barrier)
_ (.free post-present-barrier)
err (VK11/vkEndCommandBuffer command-buffer)]
(util/assert-vk-success err "Failed to wait for idle queue")
(submit-command-buffer queue command-buffer)))
(defn- recreate-swapchain
([]
(reset! resources (recreate-swapchain @resources)))
([{:keys [swapchain setup-command-buffer physical-device width height
color-format-and-space device surface queue framebuffers pipeline
render-pass render-command-buffers render-command-pool vertices]
:as resources}]
(let [cmd-buf-info (.. (VkCommandBufferBeginInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO)
(pNext 0))
err (VK11/vkBeginCommandBuffer setup-command-buffer cmd-buf-info)
_ (.free cmd-buf-info)
_ (util/assert-vk-success err "Failed to begin setup command buffer")
old-chain (if swapchain
(:swapchain-handle swapchain)
VK11/VK_NULL_HANDLE)
{:keys [color-format color-space]} color-format-and-space
swapchain (create-swapchain device physical-device surface old-chain
setup-command-buffer width height color-format
color-space)
err (VK11/vkEndCommandBuffer setup-command-buffer)
_ (util/assert-vk-success err "Failed to end setup command buffer")]
(submit-command-buffer queue setup-command-buffer)
(VK11/vkQueueWaitIdle queue)
(when framebuffers
(dotimes [i (alength framebuffers)]
(VK11/vkDestroyFramebuffer device (aget framebuffers i) nil)))
(when render-command-buffers
(VK11/vkResetCommandPool device render-command-pool vk-flags-none))
(let [framebuffers (create-framebuffers device swapchain render-pass
width height)
render-command-buffers (create-render-command-buffers device render-command-pool framebuffers render-pass width height pipeline (:vertex-buffer vertices) swapchain)]
(assoc resources
:swapchain swapchain
:framebuffers framebuffers
:render-command-buffers render-command-buffers
:must-recreate? false)))))
(defn -main
[& args]
(assert (GLFW/glfwInit) "Failed to initialize GLFW")
(assert (GLFWVulkan/glfwVulkanSupported) "GLFW failed to load Vulkan")
(let [req-ext (GLFWVulkan/glfwGetRequiredInstanceExtensions)
_ (assert req-ext "Failed to find list of required Vulkan extensions")
instance (create-instance req-ext)
debug-callback-f (reify VkDebugReportCallbackEXTI
(invoke [this flags type object loc message-code
p-layer-prefix p-message p-user-data]
(binding [*out* *err*]
(println (str "ERROR OCCURED: "
(VkDebugReportCallbackEXT/getString p-message))))
0))
debug-callback (VkDebugReportCallbackEXT/create debug-callback-f)
debug-flags (bit-or EXTDebugReport/VK_DEBUG_REPORT_ERROR_BIT_EXT
EXTDebugReport/VK_DEBUG_REPORT_WARNING_BIT_EXT)
debug-callback-handle (setup-debugging instance
debug-flags
debug-callback)
physical-device (get-first-physical-device instance)
queue-family (create-device-and-get-graphics-queue-family physical-device)
device (:device queue-family)
queue-family-index (:queue-family-index queue-family)
memory-props (:memory-properties queue-family)
_ (do
(GLFW/glfwDefaultWindowHints)
(GLFW/glfwWindowHint GLFW/GLFW_CLIENT_API GLFW/GLFW_NO_API)
(GLFW/glfwWindowHint GLFW/GLFW_VISIBLE GLFW/GLFW_FALSE))
window (GLFW/glfwCreateWindow 800 600 (util/utf8 "GLFW Vulkan Demo") 0 0)
key-callback (reify GLFWKeyCallbackI
(invoke [this window key scancode action mods]
(when (= action GLFW/GLFW_RELEASE)
(when (= key GLFW/GLFW_KEY_ESCAPE)
(GLFW/glfwSetWindowShouldClose window true)))))
_ (GLFW/glfwSetKeyCallback window (GLFWKeyCallback/create key-callback))
p-surface (MemoryUtil/memAllocLong 1)
err (GLFWVulkan/glfwCreateWindowSurface instance window nil p-surface)
surface (.get p-surface 0)
_ (util/assert-vk-success err "Failed to create surface")
color-format-and-space (get-color-format-and-space physical-device
surface)
command-pool (create-command-pool device queue-family-index)
setup-command-buffer (create-command-buffer device command-pool)
post-present-command-buffer (create-command-buffer device command-pool)
queue (create-device-queue device queue-family-index)
render-pass (create-render-pass device (:color-format color-format-and-space))
render-command-pool (create-command-pool device queue-family-index)
vertices (create-vertices memory-props device)
pipeline (create-pipeline device render-pass (:create-info vertices))
window-size-callback (reify GLFWWindowSizeCallbackI
(invoke [this window width height]
(when (and (pos? width) (pos? height))
(swap! resources assoc
:width width
:height height
:must-recreate? true))))
_
(swap! resources assoc
:setup-command-buffer setup-command-buffer
:color-format-and-space color-format-and-space
:command-pool command-pool
:post-present-command-buffer post-present-command-buffer
:queue queue
:render-pass render-pass
:render-command-pool render-command-pool
:vertices vertices
:pipeline pipeline
:physical-device physical-device
:device device
:surface surface)
_ (do
(GLFW/glfwSetWindowSizeCallback window window-size-callback)
(GLFW/glfwShowWindow window))
p-image-index (MemoryUtil/memAllocInt 1)
current-buffer (volatile! 0)
p-command-buffers (MemoryUtil/memAllocPointer 1)
p-swapchains (MemoryUtil/memAllocLong 1)
p-image-acquired-semaphore (MemoryUtil/memAllocLong 1)
p-render-complete-semaphore (MemoryUtil/memAllocLong 1)
semaphore-create-info (.. (VkSemaphoreCreateInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO)
(pNext 0)
(flags vk-flags-none))
p-wait-dst-stage-mask (doto (MemoryUtil/memAllocInt 1)
(.put 0 VK11/VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT))
submit-info (.. (VkSubmitInfo/calloc)
(sType VK11/VK_STRUCTURE_TYPE_SUBMIT_INFO)
(pNext 0)
(waitSemaphoreCount (.remaining p-image-acquired-semaphore))
(pWaitSemaphores p-image-acquired-semaphore)
(pWaitDstStageMask p-wait-dst-stage-mask)
(pCommandBuffers p-command-buffers)
(pSignalSemaphores p-render-complete-semaphore))
present-info (.. (VkPresentInfoKHR/calloc)
(sType KHRSwapchain/VK_STRUCTURE_TYPE_PRESENT_INFO_KHR)
(pNext 0)
(pWaitSemaphores p-render-complete-semaphore)
(swapchainCount (.remaining p-swapchains))
(pSwapchains p-swapchains)
(pImageIndices p-image-index)
(pResults nil))]
(try
(while (not (GLFW/glfwWindowShouldClose window))
(GLFW/glfwPollEvents)
(when (:must-recreate? @resources)
(recreate-swapchain))
(let [err (VK11/vkCreateSemaphore device
semaphore-create-info
nil
p-image-acquired-semaphore)
_ (util/assert-vk-success err "Failed to create image acquired semaphore")
err (VK11/vkCreateSemaphore device
semaphore-create-info
nil
p-render-complete-semaphore)
_ (util/assert-vk-success err "Failed to create render complete semaphore")
err (KHRSwapchain/vkAcquireNextImageKHR device
(get-in @resources
[:swapchain :swapchain-handle])
uint64-max
(.get p-image-acquired-semaphore 0)
VK11/VK_NULL_HANDLE
p-image-index)
_ (util/assert-vk-success err "Failed to acquire next swapchain image")
_ (.put p-command-buffers 0 (aget (:render-command-buffers @resources) @current-buffer))
err (VK11/vkQueueSubmit queue submit-info VK11/VK_NULL_HANDLE)
_ (util/assert-vk-success err "Failed to submit render queue")
_ (.put p-swapchains 0 (get-in @resources
[:swapchain :swapchain-handle]))
err (KHRSwapchain/vkQueuePresentKHR queue present-info)
_ (util/assert-vk-success err "Failed to present the swapchain image")]
(VK11/vkQueueWaitIdle queue)
(VK11/vkDestroySemaphore device
(.get p-image-acquired-semaphore 0)
nil)
(VK11/vkDestroySemaphore device
(.get p-render-complete-semaphore 0)
nil)
(submit-post-present-barrier (aget (:images (:swapchain @resources))
@current-buffer)
post-present-command-buffer
queue)))
(finally
(.free present-info)
(MemoryUtil/memFree p-wait-dst-stage-mask)
(.free submit-info)
(MemoryUtil/memFree p-image-acquired-semaphore)
(MemoryUtil/memFree p-render-complete-semaphore)
(.free semaphore-create-info)
(MemoryUtil/memFree p-swapchains)
(MemoryUtil/memFree p-command-buffers)
(EXTDebugReport/vkDestroyDebugReportCallbackEXT instance
debug-callback-handle
nil)
;; (MemoryUtil/memFree window-size-callback)
;; (.free key-callback)
(GLFW/glfwDestroyWindow window)
(GLFW/glfwTerminate)))))
@gzmask
Copy link

gzmask commented Feb 11, 2022

Awesome example! Can you also post your deps.edn or project.clj file for this?

@jdf-id-au
Copy link

And the vk.ray.tutorials.util implementation? Pretty please? 🎁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment