Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,21 @@ lazy val root = (project in file("."))
"org.lwjgl" % "lwjgl-vma" % lwjglVersion,
"org.lwjgl" % "lwjgl" % lwjglVersion classifier lwjglNatives,
"org.lwjgl" % "lwjgl-vma" % lwjglVersion classifier lwjglNatives,
"org.lwjgl" % "lwjgl-glfw" % lwjglVersion,
"org.lwjgl" % "lwjgl-glfw" % lwjglVersion classifier lwjglNatives,
"org.joml" % "joml" % jomlVersion,
"commons-io" % "commons-io" % "2.16.1",
"org.slf4j" % "slf4j-api" % "1.7.30",
"org.slf4j" % "slf4j-simple" % "1.7.30" % Test,
"org.scalameta" % "munit_3" % "1.0.0" % Test,
"org.junit.jupiter" % "junit-jupiter" % "5.6.2" % Test,
"org.junit.jupiter" % "junit-jupiter-engine" % "5.7.2" % Test,
"org.scalatest" %% "scalatest" % "3.2.16" % Test, // Added ScalaTest dependency
"com.lihaoyi" %% "sourcecode" % "0.4.3-M5"
)
),
Test / fork := true,
mainClass := Some("com.computenode.cyfra.app.Main")
)

lazy val vulkanSdk = System.getenv("VULKAN_SDK")
javaOptions += s"-Dorg.lwjgl.vulkan.libname=$vulkanSdk/lib/libvulkan.1.dylib"

javaOptions += "-Dorg.lwjgl.vulkan.libname=C:\\Windows\\System32\\vulkan-1.dll"
88 changes: 87 additions & 1 deletion src/main/scala/io/computenode/cyfra/vulkan/VulkanContext.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package io.computenode.cyfra.vulkan

import io.computenode.cyfra.vulkan.command.{CommandPool, Queue, StandardCommandPool}
import io.computenode.cyfra.vulkan.core.{DebugCallback, Device, Instance}
import io.computenode.cyfra.vulkan.core.{DebugCallback, Device, Instance, Surface, SurfaceCapabilities}
import io.computenode.cyfra.vulkan.memory.{Allocator, DescriptorPool}
import io.computenode.cyfra.vulkan.util.Util.{check, pushStack}
import org.lwjgl.vulkan.KHRSurface.*
import org.lwjgl.vulkan.VK10.*
import org.lwjgl.vulkan.{VkSurfaceCapabilitiesKHR, VkSurfaceFormatKHR}

import scala.jdk.CollectionConverters.given

/** @author
* MarconZet Created 13.04.2020
Expand All @@ -24,6 +30,86 @@ private[cyfra] class VulkanContext(val enableValidationLayers: Boolean = false)
val descriptorPool: DescriptorPool = new DescriptorPool(device)
val commandPool: CommandPool = new StandardCommandPool(device, computeQueue)

/** Get surface capabilities for a surface
*
* @param surface The surface to query capabilities for
* @return A SurfaceCapabilities object containing the queried capabilities
*/
def getSurfaceCapabilities(surface: Surface): SurfaceCapabilities = {
new SurfaceCapabilities(device.physicalDevice, surface)
}

/** Get available surface formats for a surface
*
* @param surface The surface to query formats for
* @return A list of supported surface formats
*/
def getSurfaceFormats(surface: Surface): List[VkSurfaceFormatKHR] = pushStack { stack =>
val countPtr = stack.callocInt(1)
check(
vkGetPhysicalDeviceSurfaceFormatsKHR(device.physicalDevice, surface.get, countPtr, null),
"Failed to get surface format count"
)

val count = countPtr.get(0)
if (count == 0) {
return List.empty
}

val surfaceFormats = VkSurfaceFormatKHR.calloc(count, stack)
check(
vkGetPhysicalDeviceSurfaceFormatsKHR(device.physicalDevice, surface.get, countPtr, surfaceFormats),
"Failed to get surface formats"
)

surfaceFormats.iterator().asScala.toList
}

/** Get available presentation modes for a surface
*
* @param surface The surface to query presentation modes for
* @return A list of supported presentation modes
*/
def getPresentModes(surface: Surface): List[Int] = pushStack { stack =>
val countPtr = stack.callocInt(1)
check(
vkGetPhysicalDeviceSurfacePresentModesKHR(device.physicalDevice, surface.get, countPtr, null),
"Failed to get presentation mode count"
)

val count = countPtr.get(0)
if (count == 0) {
return List.empty
}

val presentModes = stack.callocInt(count)
check(
vkGetPhysicalDeviceSurfacePresentModesKHR(device.physicalDevice, surface.get, countPtr, presentModes),
"Failed to get presentation modes"
)

val result = collection.mutable.ListBuffer[Int]()
for (i <- 0 until count) {
result += presentModes.get(i)
}
result.toList
}

/** Check if a queue family supports presentation to a surface
*
* @param queueFamilyIndex The queue family index to check
* @param surface The surface to check presentation support for
* @return Whether the queue family supports presentation to the surface
*/
def isQueueFamilyPresentSupported(queueFamilyIndex: Int, surface: Surface): Boolean = pushStack { stack =>
val pSupported = stack.callocInt(1)
check(
vkGetPhysicalDeviceSurfaceSupportKHR(device.physicalDevice, queueFamilyIndex, surface.get, pSupported),
"Failed to check queue family presentation support"
)
pSupported.get(0) == VK_TRUE
}

def destroy(): Unit = {
commandPool.destroy()
descriptorPool.destroy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.lwjgl.vulkan.EXTDebugReport.VK_EXT_DEBUG_REPORT_EXTENSION_NAME
import org.lwjgl.vulkan.KHRPortabilityEnumeration.{VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME}
import org.lwjgl.vulkan.VK10.*
import org.lwjgl.vulkan.VK13.*
import org.lwjgl.vulkan.KHRSurface.VK_KHR_SURFACE_EXTENSION_NAME

import scala.collection.mutable
import scala.jdk.CollectionConverters.given
Expand All @@ -21,6 +22,7 @@ import scala.util.chaining.*
object Instance {
val ValidationLayersExtensions: Seq[String] = List(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)
val MacOsExtensions: Seq[String] = List(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)
val PlatformExtensions: Seq[String] = Seq(VK_KHR_SURFACE_EXTENSION_NAME, "VK_KHR_win32_surface")

lazy val (extensions, layers): (Seq[String], Seq[String]) = pushStack { stack =>
val ip = stack.ints(1)
Expand Down Expand Up @@ -94,6 +96,7 @@ private[cyfra] class Instance(enableValidationLayers: Boolean) extends VulkanObj
val extensions = mutable.Buffer.from(Instance.MacOsExtensions)
if (enableValidationLayers)
extensions.addAll(Instance.ValidationLayersExtensions)
extensions.addAll(Instance.PlatformExtensions)

val ppEnabledExtensionNames = stack.callocPointer(extensions.size)
extensions.foreach(x => ppEnabledExtensionNames.put(stack.ASCII(x)))
Expand Down
60 changes: 60 additions & 0 deletions src/main/scala/io/computenode/cyfra/vulkan/core/Surface.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.computenode.cyfra.vulkan.core

import io.computenode.cyfra.vulkan.util.Util.{check, pushStack}
import io.computenode.cyfra.vulkan.util.{VulkanAssertionError, VulkanObjectHandle}
import org.lwjgl.glfw.GLFWVulkan
import org.lwjgl.system.MemoryStack
import org.lwjgl.vulkan.KHRSurface.*
import org.lwjgl.vulkan.VK10.*
import org.lwjgl.glfw.GLFW
import org.lwjgl.vulkan.{VkPhysicalDevice, VkSurfaceCapabilitiesKHR}

/** Class that encapsulates a Vulkan surface (VkSurfaceKHR)
*
* @author
* Created based on project conventions
*/
private[cyfra] class Surface(instance: Instance, windowHandle: Long) extends VulkanObjectHandle {

protected val handle: Long = pushStack { stack =>
val pSurface = stack.callocLong(1)
check(
GLFWVulkan.glfwCreateWindowSurface(instance.get, windowHandle, null, pSurface),
"Failed to create window surface"
)
pSurface.get(0)
}

/** Get surface capabilities for a physical device
*
* @param physicalDevice The physical device to query capabilities for
* @return Surface capabilities structure
*/
def getCapabilities(physicalDevice: VkPhysicalDevice): VkSurfaceCapabilitiesKHR = pushStack { stack =>
val capabilities = VkSurfaceCapabilitiesKHR.calloc(stack)
check(
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, handle, capabilities),
"Failed to get surface capabilities"
)
capabilities
}

/** Check if the physical device supports presentation on this surface
*
* @param physicalDevice The physical device to check
* @param queueFamilyIndex The queue family index to check
* @return True if presentation is supported
*/
def supportsPresentationFrom(physicalDevice: VkPhysicalDevice, queueFamilyIndex: Int): Boolean = pushStack { stack =>
val pSupported = stack.callocInt(1)
check(
vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, handle, pSupported),
"Failed to check presentation support"
)
pSupported.get(0) == VK_TRUE
}

override protected def close(): Unit = {
vkDestroySurfaceKHR(instance.get, handle, null)
}
}
Loading