From 3a36a78392ee5babbced92029435fc0e83bee73a Mon Sep 17 00:00:00 2001 From: halotroop2288 Date: Mon, 2 Mar 2020 02:14:08 -0800 Subject: [PATCH] OpenGL 4.6 YeS --- .../github/hydos/ginger/VulkanStarter.java | 1461 ----------------- .../hydos/ginger/engine/common/io/Window.java | 11 + 2 files changed, 11 insertions(+), 1461 deletions(-) delete mode 100644 src/main/java/com/github/hydos/ginger/VulkanStarter.java diff --git a/src/main/java/com/github/hydos/ginger/VulkanStarter.java b/src/main/java/com/github/hydos/ginger/VulkanStarter.java deleted file mode 100644 index edf8ff8..0000000 --- a/src/main/java/com/github/hydos/ginger/VulkanStarter.java +++ /dev/null @@ -1,1461 +0,0 @@ -/* - * Copyright LWJGL. All rights reserved. - * License terms: https://www.lwjgl.org/license - */ -package com.github.hydos.ginger; - -import static org.lwjgl.glfw.GLFW.*; -import static org.lwjgl.glfw.GLFWVulkan.*; -import static org.lwjgl.system.MemoryUtil.*; -import static org.lwjgl.vulkan.EXTDebugReport.*; -import static org.lwjgl.vulkan.KHRSurface.*; -import static org.lwjgl.vulkan.KHRSwapchain.*; -import static org.lwjgl.vulkan.VK12.*; - -import java.io.IOException; -import java.nio.*; - -import org.joml.Matrix4f; -import org.lwjgl.PointerBuffer; -import org.lwjgl.glfw.*; -import org.lwjgl.vulkan.*; - -import com.github.hydos.ginger.engine.vulkan.utils.VKUtils; - -/** - * Renders two rotating triangles on a cornflower blue background on a GLFW window with Vulkan. - *

- * This is like the {@link ColoredRotatingQuadDemo}, but it adds a depth buffer to avoid false overdraw. - * - * @author Kai Burjack - */ -public class VulkanStarter { - private static boolean debug = System.getProperty("NDEBUG") == null; - - private static ByteBuffer[] layers = { - memUTF8("VK_LAYER_LUNARG_standard_validation"), - }; - - /** - * This is just -1L, but it is nicer as a symbolic constant. - */ - private static final long UINT64_MAX = 0xFFFFFFFFFFFFFFFFL; - - /** - * Create a Vulkan instance using LWJGL 3. - * - * @return the VkInstance handle - */ - private static VkInstance createInstance(PointerBuffer requiredExtensions) { - VkApplicationInfo appInfo = VkApplicationInfo.calloc() - .sType(VK_STRUCTURE_TYPE_APPLICATION_INFO) - .apiVersion(VK_API_VERSION_1_2); - PointerBuffer ppEnabledExtensionNames = memAllocPointer(requiredExtensions.remaining() + 1); - ppEnabledExtensionNames.put(requiredExtensions); - ByteBuffer VK_EXT_DEBUG_REPORT_EXTENSION = memUTF8(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); - ppEnabledExtensionNames.put(VK_EXT_DEBUG_REPORT_EXTENSION); - ppEnabledExtensionNames.flip(); - PointerBuffer ppEnabledLayerNames = memAllocPointer(layers.length); - for (int i = 0; debug && i < layers.length; i++) - ppEnabledLayerNames.put(layers[i]); - ppEnabledLayerNames.flip(); - VkInstanceCreateInfo pCreateInfo = VkInstanceCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO) - .pApplicationInfo(appInfo) - .ppEnabledExtensionNames(ppEnabledExtensionNames) - .ppEnabledLayerNames(ppEnabledLayerNames); - PointerBuffer pInstance = memAllocPointer(1); - int err = vkCreateInstance(pCreateInfo, null, pInstance); - long instance = pInstance.get(0); - memFree(pInstance); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create VkInstance: " + VKUtils.translateVulkanResult(err)); - } - VkInstance ret = new VkInstance(instance, pCreateInfo); - pCreateInfo.free(); - memFree(ppEnabledLayerNames); - memFree(VK_EXT_DEBUG_REPORT_EXTENSION); - memFree(ppEnabledExtensionNames); - memFree(appInfo.pApplicationName()); - memFree(appInfo.pEngineName()); - appInfo.free(); - return ret; - } - - private static long setupDebugging(VkInstance instance, int flags, VkDebugReportCallbackEXT callback) { - VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = VkDebugReportCallbackCreateInfoEXT.calloc() - .sType(VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT) - .pfnCallback(callback) - .flags(flags); - LongBuffer pCallback = memAllocLong(1); - int err = vkCreateDebugReportCallbackEXT(instance, dbgCreateInfo, null, pCallback); - long callbackHandle = pCallback.get(0); - memFree(pCallback); - dbgCreateInfo.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create VkInstance: " + VKUtils.translateVulkanResult(err)); - } - return callbackHandle; - } - - private static VkPhysicalDevice getFirstPhysicalDevice(VkInstance instance) { - IntBuffer pPhysicalDeviceCount = memAllocInt(1); - int err = vkEnumeratePhysicalDevices(instance, pPhysicalDeviceCount, null); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to get number of physical devices: " + VKUtils.translateVulkanResult(err)); - } - PointerBuffer pPhysicalDevices = memAllocPointer(pPhysicalDeviceCount.get(0)); - err = vkEnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices); - long physicalDevice = pPhysicalDevices.get(0); - memFree(pPhysicalDeviceCount); - memFree(pPhysicalDevices); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to get physical devices: " + VKUtils.translateVulkanResult(err)); - } - return new VkPhysicalDevice(physicalDevice, instance); - } - - private static class DeviceAndGraphicsQueueFamily { - VkDevice device; - int queueFamilyIndex; - VkPhysicalDeviceMemoryProperties memoryProperties; - } - - private static DeviceAndGraphicsQueueFamily createDeviceAndGetGraphicsQueueFamily(VkPhysicalDevice physicalDevice) { - IntBuffer pQueueFamilyPropertyCount = memAllocInt(1); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, null); - int queueCount = pQueueFamilyPropertyCount.get(0); - VkQueueFamilyProperties.Buffer queueProps = VkQueueFamilyProperties.calloc(queueCount); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, queueProps); - memFree(pQueueFamilyPropertyCount); - int graphicsQueueFamilyIndex; - for (graphicsQueueFamilyIndex = 0; graphicsQueueFamilyIndex < queueCount; graphicsQueueFamilyIndex++) { - if ((queueProps.get(graphicsQueueFamilyIndex).queueFlags() & VK_QUEUE_GRAPHICS_BIT) != 0) - break; - } - queueProps.free(); - FloatBuffer pQueuePriorities = memAllocFloat(1).put(0.0f); - pQueuePriorities.flip(); - VkDeviceQueueCreateInfo.Buffer queueCreateInfo = VkDeviceQueueCreateInfo.calloc(1) - .sType(VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO) - .queueFamilyIndex(graphicsQueueFamilyIndex) - .pQueuePriorities(pQueuePriorities); - - PointerBuffer extensions = memAllocPointer(1); - ByteBuffer VK_KHR_SWAPCHAIN_EXTENSION = memUTF8(VK_KHR_SWAPCHAIN_EXTENSION_NAME); - extensions.put(VK_KHR_SWAPCHAIN_EXTENSION); - extensions.flip(); - PointerBuffer ppEnabledLayerNames = memAllocPointer(layers.length); - for (int i = 0; debug && i < layers.length; i++) - ppEnabledLayerNames.put(layers[i]); - ppEnabledLayerNames.flip(); - - VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO) - .pQueueCreateInfos(queueCreateInfo) - .ppEnabledExtensionNames(extensions) - .ppEnabledLayerNames(ppEnabledLayerNames); - - PointerBuffer pDevice = memAllocPointer(1); - int err = vkCreateDevice(physicalDevice, deviceCreateInfo, null, pDevice); - long device = pDevice.get(0); - memFree(pDevice); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create device: " + VKUtils.translateVulkanResult(err)); - } - - VkPhysicalDeviceMemoryProperties memoryProperties = VkPhysicalDeviceMemoryProperties.calloc(); - vkGetPhysicalDeviceMemoryProperties(physicalDevice, memoryProperties); - - DeviceAndGraphicsQueueFamily ret = new DeviceAndGraphicsQueueFamily(); - ret.device = new VkDevice(device, physicalDevice, deviceCreateInfo); - ret.queueFamilyIndex = graphicsQueueFamilyIndex; - ret.memoryProperties = memoryProperties; - - deviceCreateInfo.free(); - memFree(ppEnabledLayerNames); - memFree(VK_KHR_SWAPCHAIN_EXTENSION); - memFree(extensions); - memFree(pQueuePriorities); - return ret; - } - - private static boolean getSupportedDepthFormat(VkPhysicalDevice physicalDevice, IntBuffer depthFormat) { - // Since all depth formats may be optional, we need to find a suitable depth format to use - // Start with the highest precision packed format - int[] depthFormats = { - VK_FORMAT_D32_SFLOAT_S8_UINT, - VK_FORMAT_D32_SFLOAT, - VK_FORMAT_D24_UNORM_S8_UINT, - VK_FORMAT_D16_UNORM_S8_UINT, - VK_FORMAT_D16_UNORM - }; - - VkFormatProperties formatProps = VkFormatProperties.calloc(); - for (int format : depthFormats) { - vkGetPhysicalDeviceFormatProperties(physicalDevice, format, formatProps); - // Format must support depth stencil attachment for optimal tiling - if ((formatProps.optimalTilingFeatures() & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0) { - depthFormat.put(0, format); - return true; - } - } - return false; - } - - private static class ColorAndDepthFormatAndSpace { - int colorFormat; - int colorSpace; - int depthFormat; - } - - private static ColorAndDepthFormatAndSpace getColorFormatAndSpace(VkPhysicalDevice physicalDevice, long surface) { - IntBuffer pQueueFamilyPropertyCount = memAllocInt(1); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, null); - int queueCount = pQueueFamilyPropertyCount.get(0); - VkQueueFamilyProperties.Buffer queueProps = VkQueueFamilyProperties.calloc(queueCount); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, queueProps); - memFree(pQueueFamilyPropertyCount); - - // Iterate over each queue to learn whether it supports presenting: - IntBuffer supportsPresent = memAllocInt(queueCount); - for (int i = 0; i < queueCount; i++) { - supportsPresent.position(i); - int err = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface, supportsPresent); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to physical device surface support: " + VKUtils.translateVulkanResult(err)); - } - } - - // Search for a graphics and a present queue in the array of queue families, try to find one that supports both - int graphicsQueueNodeIndex = Integer.MAX_VALUE; - int presentQueueNodeIndex = Integer.MAX_VALUE; - for (int i = 0; i < queueCount; i++) { - if ((queueProps.get(i).queueFlags() & VK_QUEUE_GRAPHICS_BIT) != 0) { - if (graphicsQueueNodeIndex == Integer.MAX_VALUE) { - graphicsQueueNodeIndex = i; - } - if (supportsPresent.get(i) == VK_TRUE) { - graphicsQueueNodeIndex = i; - presentQueueNodeIndex = i; - break; - } - } - } - queueProps.free(); - if (presentQueueNodeIndex == Integer.MAX_VALUE) { - // If there's no queue that supports both present and graphics try to find a separate present queue - for (int i = 0; i < queueCount; ++i) { - if (supportsPresent.get(i) == VK_TRUE) { - presentQueueNodeIndex = i; - break; - } - } - } - memFree(supportsPresent); - - // Generate error if could not find both a graphics and a present queue - if (graphicsQueueNodeIndex == Integer.MAX_VALUE) { - throw new AssertionError("No graphics queue found"); - } - if (presentQueueNodeIndex == Integer.MAX_VALUE) { - throw new AssertionError("No presentation queue found"); - } - if (graphicsQueueNodeIndex != presentQueueNodeIndex) { - throw new AssertionError("Presentation queue != graphics queue"); - } - - // Get list of supported formats - IntBuffer pFormatCount = memAllocInt(1); - int err = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pFormatCount, null); - int formatCount = pFormatCount.get(0); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to query number of physical device surface formats: " + VKUtils.translateVulkanResult(err)); - } - - VkSurfaceFormatKHR.Buffer surfFormats = VkSurfaceFormatKHR.calloc(formatCount); - err = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pFormatCount, surfFormats); - memFree(pFormatCount); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to query physical device surface formats: " + VKUtils.translateVulkanResult(err)); - } - - int colorFormat; - if (formatCount == 1 && surfFormats.get(0).format() == VK_FORMAT_UNDEFINED) { - colorFormat = VK_FORMAT_B8G8R8A8_UNORM; - } else { - colorFormat = surfFormats.get(0).format(); - } - int colorSpace = surfFormats.get(0).colorSpace(); - surfFormats.free(); - - // Find suitable depth format - IntBuffer pDepthFormat = memAllocInt(1).put(0, -1); - getSupportedDepthFormat(physicalDevice, pDepthFormat); - int depthFormat = pDepthFormat.get(0); - - ColorAndDepthFormatAndSpace ret = new ColorAndDepthFormatAndSpace(); - ret.colorFormat = colorFormat; - ret.colorSpace = colorSpace; - ret.depthFormat = depthFormat; - return ret; - } - - private static long createCommandPool(VkDevice device, int queueNodeIndex) { - VkCommandPoolCreateInfo cmdPoolInfo = VkCommandPoolCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO) - .queueFamilyIndex(queueNodeIndex) - .flags(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); - LongBuffer pCmdPool = memAllocLong(1); - int err = vkCreateCommandPool(device, cmdPoolInfo, null, pCmdPool); - long commandPool = pCmdPool.get(0); - cmdPoolInfo.free(); - memFree(pCmdPool); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create command pool: " + VKUtils.translateVulkanResult(err)); - } - return commandPool; - } - - private static VkQueue createDeviceQueue(VkDevice device, int queueFamilyIndex) { - PointerBuffer pQueue = memAllocPointer(1); - vkGetDeviceQueue(device, queueFamilyIndex, 0, pQueue); - long queue = pQueue.get(0); - memFree(pQueue); - return new VkQueue(queue, device); - } - - private static VkCommandBuffer createCommandBuffer(VkDevice device, long commandPool) { - VkCommandBufferAllocateInfo cmdBufAllocateInfo = VkCommandBufferAllocateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO) - .commandPool(commandPool) - .level(VK_COMMAND_BUFFER_LEVEL_PRIMARY) - .commandBufferCount(1); - PointerBuffer pCommandBuffer = memAllocPointer(1); - int err = vkAllocateCommandBuffers(device, cmdBufAllocateInfo, pCommandBuffer); - cmdBufAllocateInfo.free(); - long commandBuffer = pCommandBuffer.get(0); - memFree(pCommandBuffer); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to allocate command buffer: " + VKUtils.translateVulkanResult(err)); - } - return new VkCommandBuffer(commandBuffer, device); - } - - private static class Swapchain { - long swapchainHandle; - long[] images; - long[] imageViews; - } - - private static Swapchain createSwapChain(VkDevice device, VkPhysicalDevice physicalDevice, long surface, long oldSwapChain, VkCommandBuffer commandBuffer, int newWidth, - int newHeight, int colorFormat, int colorSpace) { - int err; - // Get physical device surface properties and formats - VkSurfaceCapabilitiesKHR surfCaps = VkSurfaceCapabilitiesKHR.calloc(); - err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, surfCaps); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to get physical device surface capabilities: " + VKUtils.translateVulkanResult(err)); - } - - IntBuffer pPresentModeCount = memAllocInt(1); - err = vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, null); - int presentModeCount = pPresentModeCount.get(0); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to get number of physical device surface presentation modes: " + VKUtils.translateVulkanResult(err)); - } - - IntBuffer pPresentModes = memAllocInt(presentModeCount); - err = vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, pPresentModes); - memFree(pPresentModeCount); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to get physical device surface presentation modes: " + VKUtils.translateVulkanResult(err)); - } - - // Try to use mailbox mode. Low latency and non-tearing - int swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; - for (int i = 0; i < presentModeCount; i++) { - if (pPresentModes.get(i) == VK_PRESENT_MODE_MAILBOX_KHR) { - swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR; - break; - } - if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (pPresentModes.get(i) == VK_PRESENT_MODE_IMMEDIATE_KHR)) { - swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; - } - } - memFree(pPresentModes); - - // Determine the number of images - int desiredNumberOfSwapchainImages = surfCaps.minImageCount() + 1; - if ((surfCaps.maxImageCount() > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount())) { - desiredNumberOfSwapchainImages = surfCaps.maxImageCount(); - } - - VkExtent2D currentExtent = surfCaps.currentExtent(); - int currentWidth = currentExtent.width(); - int currentHeight = currentExtent.height(); - if (currentWidth != -1 && currentHeight != -1) { - width = currentWidth; - height = currentHeight; - } else { - width = newWidth; - height = newHeight; - } - - int preTransform; - if ((surfCaps.supportedTransforms() & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) != 0) { - preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - } else { - preTransform = surfCaps.currentTransform(); - } - surfCaps.free(); - - VkSwapchainCreateInfoKHR swapchainCI = VkSwapchainCreateInfoKHR.calloc() - .sType(VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) - .surface(surface) - .minImageCount(desiredNumberOfSwapchainImages) - .imageFormat(colorFormat) - .imageColorSpace(colorSpace) - .imageUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) - .preTransform(preTransform) - .imageArrayLayers(1) - .imageSharingMode(VK_SHARING_MODE_EXCLUSIVE) - .presentMode(swapchainPresentMode) - .oldSwapchain(oldSwapChain) - .clipped(true) - .compositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR); - swapchainCI.imageExtent() - .width(width) - .height(height); - LongBuffer pSwapChain = memAllocLong(1); - err = vkCreateSwapchainKHR(device, swapchainCI, null, pSwapChain); - swapchainCI.free(); - long swapChain = pSwapChain.get(0); - memFree(pSwapChain); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create swap chain: " + VKUtils.translateVulkanResult(err)); - } - - // If we just re-created an existing swapchain, we should destroy the old swapchain at this point. - // Note: destroying the swapchain also cleans up all its associated presentable images once the platform is done with them. - if (oldSwapChain != VK_NULL_HANDLE) { - vkDestroySwapchainKHR(device, oldSwapChain, null); - } - - IntBuffer pImageCount = memAllocInt(1); - err = vkGetSwapchainImagesKHR(device, swapChain, pImageCount, null); - int imageCount = pImageCount.get(0); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to get number of swapchain images: " + VKUtils.translateVulkanResult(err)); - } - - LongBuffer pSwapchainImages = memAllocLong(imageCount); - err = vkGetSwapchainImagesKHR(device, swapChain, pImageCount, pSwapchainImages); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to get swapchain images: " + VKUtils.translateVulkanResult(err)); - } - memFree(pImageCount); - - long[] images = new long[imageCount]; - long[] imageViews = new long[imageCount]; - LongBuffer pBufferView = memAllocLong(1); - VkImageViewCreateInfo colorAttachmentView = VkImageViewCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO) - .format(colorFormat) - .viewType(VK_IMAGE_VIEW_TYPE_2D); - colorAttachmentView.subresourceRange() - .aspectMask(VK_IMAGE_ASPECT_COLOR_BIT) - .levelCount(1) - .layerCount(1); - for (int i = 0; i < imageCount; i++) { - images[i] = pSwapchainImages.get(i); - colorAttachmentView.image(images[i]); - err = vkCreateImageView(device, colorAttachmentView, null, pBufferView); - imageViews[i] = pBufferView.get(0); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create image view: " + VKUtils.translateVulkanResult(err)); - } - } - colorAttachmentView.free(); - memFree(pBufferView); - memFree(pSwapchainImages); - - Swapchain ret = new Swapchain(); - ret.images = images; - ret.imageViews = imageViews; - ret.swapchainHandle = swapChain; - return ret; - } - - private static class DepthStencil { - long view; - } - - private static DepthStencil createDepthStencil(VkDevice device, VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties, int depthFormat, VkCommandBuffer setupCmdBuffer) { - VkImageCreateInfo imageCreateInfo = VkImageCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO) - .imageType(VK_IMAGE_TYPE_2D) - .format(depthFormat) - .mipLevels(1) - .arrayLayers(1) - .samples(VK_SAMPLE_COUNT_1_BIT) - .tiling(VK_IMAGE_TILING_OPTIMAL) - .usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); - imageCreateInfo.extent().width(width).height(height).depth(1); - - VkMemoryAllocateInfo mem_alloc = VkMemoryAllocateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); - - VkImageViewCreateInfo depthStencilViewCreateInfo = VkImageViewCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO) - .viewType(VK_IMAGE_VIEW_TYPE_2D) - .format(depthFormat); - depthStencilViewCreateInfo.subresourceRange() - .aspectMask(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) - .levelCount(1) - .layerCount(1); - - VkMemoryRequirements memReqs = VkMemoryRequirements.calloc(); - int err; - - LongBuffer pDepthStencilImage = memAllocLong(1); - err = vkCreateImage(device, imageCreateInfo, null, pDepthStencilImage); - long depthStencilImage = pDepthStencilImage.get(0); - memFree(pDepthStencilImage); - imageCreateInfo.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create depth-stencil image: " + VKUtils.translateVulkanResult(err)); - } - vkGetImageMemoryRequirements(device, depthStencilImage, memReqs); - mem_alloc.allocationSize(memReqs.size()); - IntBuffer pMemoryTypeIndex = memAllocInt(1); - getMemoryType(physicalDeviceMemoryProperties, memReqs.memoryTypeBits(), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, pMemoryTypeIndex); - mem_alloc.memoryTypeIndex(pMemoryTypeIndex.get(0)); - memFree(pMemoryTypeIndex); - LongBuffer pDepthStencilMem = memAllocLong(1); - err = vkAllocateMemory(device, mem_alloc, null, pDepthStencilMem); - long depthStencilMem = pDepthStencilMem.get(0); - memFree(pDepthStencilMem); - mem_alloc.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create depth-stencil memory: " + VKUtils.translateVulkanResult(err)); - } - - err = vkBindImageMemory(device, depthStencilImage, depthStencilMem, 0); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to bind depth-stencil image to memory: " + VKUtils.translateVulkanResult(err)); - } - - depthStencilViewCreateInfo.image(depthStencilImage); - LongBuffer pDepthStencilView = memAllocLong(1); - err = vkCreateImageView(device, depthStencilViewCreateInfo, null, pDepthStencilView); - long depthStencilView = pDepthStencilView.get(0); - memFree(pDepthStencilView); - depthStencilViewCreateInfo.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create depth-stencil image view: " + VKUtils.translateVulkanResult(err)); - } - - DepthStencil ret = new DepthStencil(); - ret.view = depthStencilView; - return ret; - } - - private static long createRenderPass(VkDevice device, int colorFormat, int depthFormat) { - VkAttachmentDescription.Buffer attachments = VkAttachmentDescription.calloc(2); - attachments.get(0) // <- color attachment - .format(colorFormat) - .samples(VK_SAMPLE_COUNT_1_BIT) - .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) - .storeOp(VK_ATTACHMENT_STORE_OP_STORE) - .stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE) - .stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE) - .initialLayout(VK_IMAGE_LAYOUT_UNDEFINED) - .finalLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - attachments.get(1) // <- depth-stencil attachment - .format(depthFormat) - .samples(VK_SAMPLE_COUNT_1_BIT) - .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) - .storeOp(VK_ATTACHMENT_STORE_OP_STORE) - .stencilLoadOp(VK_ATTACHMENT_LOAD_OP_DONT_CARE) - .stencilStoreOp(VK_ATTACHMENT_STORE_OP_DONT_CARE) - .initialLayout(VK_IMAGE_LAYOUT_UNDEFINED) - .finalLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - - VkAttachmentReference.Buffer colorReference = VkAttachmentReference.calloc(1) - .attachment(0) - .layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - VkAttachmentReference depthReference = VkAttachmentReference.calloc() - .attachment(1) - .layout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - - VkSubpassDescription.Buffer subpass = VkSubpassDescription.calloc(1) - .pipelineBindPoint(VK_PIPELINE_BIND_POINT_GRAPHICS) - .colorAttachmentCount(colorReference.remaining()) - .pColorAttachments(colorReference) // <- only color attachment - .pDepthStencilAttachment(depthReference) // <- and depth-stencil - ; - - VkRenderPassCreateInfo renderPassInfo = VkRenderPassCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO) - .pAttachments(attachments) - .pSubpasses(subpass) - ; - - LongBuffer pRenderPass = memAllocLong(1); - int err = vkCreateRenderPass(device, renderPassInfo, null, pRenderPass); - long renderPass = pRenderPass.get(0); - memFree(pRenderPass); - renderPassInfo.free(); - depthReference.free(); - colorReference.free(); - subpass.free(); - attachments.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create clear render pass: " + VKUtils.translateVulkanResult(err)); - } - return renderPass; - } - - private static long[] createFramebuffers(VkDevice device, Swapchain swapchain, long renderPass, int width, int height, DepthStencil depthStencil) { - LongBuffer attachments = memAllocLong(2); - attachments.put(1, depthStencil.view); - VkFramebufferCreateInfo fci = VkFramebufferCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO) - .pAttachments(attachments) - .height(height) - .width(width) - .layers(1) - .renderPass(renderPass); - // Create a framebuffer for each swapchain image - long[] framebuffers = new long[swapchain.images.length]; - LongBuffer pFramebuffer = memAllocLong(1); - for (int i = 0; i < swapchain.images.length; i++) { - attachments.put(0, swapchain.imageViews[i]); - int err = vkCreateFramebuffer(device, fci, null, pFramebuffer); - long framebuffer = pFramebuffer.get(0); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create framebuffer: " + VKUtils.translateVulkanResult(err)); - } - framebuffers[i] = framebuffer; - } - memFree(attachments); - memFree(pFramebuffer); - fci.free(); - return framebuffers; - } - - private static void submitCommandBuffer(VkQueue queue, VkCommandBuffer commandBuffer) { - if (commandBuffer == null || commandBuffer.address() == NULL) - return; - VkSubmitInfo submitInfo = VkSubmitInfo.calloc() - .sType(VK_STRUCTURE_TYPE_SUBMIT_INFO); - PointerBuffer pCommandBuffers = memAllocPointer(1) - .put(commandBuffer) - .flip(); - submitInfo.pCommandBuffers(pCommandBuffers); - int err = vkQueueSubmit(queue, submitInfo, VK_NULL_HANDLE); - memFree(pCommandBuffers); - submitInfo.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to submit command buffer: " + VKUtils.translateVulkanResult(err)); - } - } - - private static long loadShader(String classPath, VkDevice device, int stage) throws IOException { - ByteBuffer shaderCode = VKUtils.glslToSpirv(classPath, stage); - int err; - VkShaderModuleCreateInfo moduleCreateInfo = VkShaderModuleCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) - .pCode(shaderCode); - LongBuffer pShaderModule = memAllocLong(1); - err = vkCreateShaderModule(device, moduleCreateInfo, null, pShaderModule); - long shaderModule = pShaderModule.get(0); - memFree(pShaderModule); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create shader module: " + VKUtils.translateVulkanResult(err)); - } - return shaderModule; - } - - private static VkPipelineShaderStageCreateInfo loadShader(VkDevice device, String classPath, int stage) throws IOException { - VkPipelineShaderStageCreateInfo shaderStage = VkPipelineShaderStageCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO) - .stage(stage) - .module(loadShader(classPath, device, stage)) - .pName(memUTF8("main")); - return shaderStage; - } - - private static boolean getMemoryType(VkPhysicalDeviceMemoryProperties deviceMemoryProperties, int typeBits, int properties, IntBuffer typeIndex) { - int bits = typeBits; - for (int i = 0; i < 32; i++) { - if ((bits & 1) == 1) { - if ((deviceMemoryProperties.memoryTypes(i).propertyFlags() & properties) == properties) { - typeIndex.put(0, i); - return true; - } - } - bits >>= 1; - } - return false; - } - - private static class Vertices { - long verticesBuf; - VkPipelineVertexInputStateCreateInfo createInfo; - } - - private static Vertices createVertices(VkPhysicalDeviceMemoryProperties deviceMemoryProperties, VkDevice device) { - ByteBuffer vertexBuffer = memAlloc(2 * 3 * (3 + 3) * 4); - FloatBuffer fb = vertexBuffer.asFloatBuffer(); - // first triangle - fb.put(-0.5f).put(-0.5f).put(0.5f).put(1.0f).put(0.0f).put(0.0f); - fb.put( 0.5f).put(-0.5f).put(0.5f).put(0.0f).put(1.0f).put(0.0f); - fb.put( 0.0f).put( 0.5f).put(0.5f).put(0.0f).put(0.0f).put(1.0f); - // second triangle - fb.put( 0.5f).put(-0.5f).put(-0.5f).put(1.0f).put(1.0f).put(0.0f); - fb.put(-0.5f).put(-0.5f).put(-0.5f).put(0.0f).put(1.0f).put(1.0f); - fb.put( 0.0f).put( 0.5f).put(-0.5f).put(1.0f).put(0.0f).put(1.0f); - - VkMemoryAllocateInfo memAlloc = VkMemoryAllocateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); - VkMemoryRequirements memReqs = VkMemoryRequirements.calloc(); - - int err; - - // Generate vertex buffer - // Setup - VkBufferCreateInfo bufInfo = VkBufferCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO) - .size(vertexBuffer.remaining()) - .usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - LongBuffer pBuffer = memAllocLong(1); - err = vkCreateBuffer(device, bufInfo, null, pBuffer); - long verticesBuf = pBuffer.get(0); - memFree(pBuffer); - bufInfo.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create vertex buffer: " + VKUtils.translateVulkanResult(err)); - } - - vkGetBufferMemoryRequirements(device, verticesBuf, memReqs); - memAlloc.allocationSize(memReqs.size()); - IntBuffer memoryTypeIndex = memAllocInt(1); - getMemoryType(deviceMemoryProperties, memReqs.memoryTypeBits(), VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, memoryTypeIndex); - memAlloc.memoryTypeIndex(memoryTypeIndex.get(0)); - memFree(memoryTypeIndex); - memReqs.free(); - - LongBuffer pMemory = memAllocLong(1); - err = vkAllocateMemory(device, memAlloc, null, pMemory); - long verticesMem = pMemory.get(0); - memFree(pMemory); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to allocate vertex memory: " + VKUtils.translateVulkanResult(err)); - } - - PointerBuffer pData = memAllocPointer(1); - err = vkMapMemory(device, verticesMem, 0, vertexBuffer.remaining(), 0, pData); - memAlloc.free(); - long data = pData.get(0); - memFree(pData); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to map vertex memory: " + VKUtils.translateVulkanResult(err)); - } - - memCopy(memAddress(vertexBuffer), data, vertexBuffer.remaining()); - memFree(vertexBuffer); - vkUnmapMemory(device, verticesMem); - err = vkBindBufferMemory(device, verticesBuf, verticesMem, 0); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to bind memory to vertex buffer: " + VKUtils.translateVulkanResult(err)); - } - - // Binding description - VkVertexInputBindingDescription.Buffer bindingDescriptor = VkVertexInputBindingDescription.calloc(1) - .binding(0) // <- we bind our vertex buffer to point 0 - .stride((3 + 3) * 4) - .inputRate(VK_VERTEX_INPUT_RATE_VERTEX); - - // Attribute descriptions - // Describes memory layout and shader attribute locations - VkVertexInputAttributeDescription.Buffer attributeDescriptions = VkVertexInputAttributeDescription.calloc(2); - // Location 0 : Position - attributeDescriptions.get(0) - .binding(0) // <- binding point used in the VkVertexInputBindingDescription - .location(0) // <- location in the shader's attribute layout (inside the shader source) - .format(VK_FORMAT_R32G32B32_SFLOAT) - .offset(0); - // Location 1 : Color - attributeDescriptions.get(1) - .binding(0) // <- binding point used in the VkVertexInputBindingDescription - .location(1) // <- location in the shader's attribute layout (inside the shader source) - .format(VK_FORMAT_R32G32B32_SFLOAT) - .offset(3 * 4); - - // Assign to vertex buffer - VkPipelineVertexInputStateCreateInfo vi = VkPipelineVertexInputStateCreateInfo.calloc(); - vi.sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO); - vi.pVertexBindingDescriptions(bindingDescriptor); - vi.pVertexAttributeDescriptions(attributeDescriptions); - - Vertices ret = new Vertices(); - ret.createInfo = vi; - ret.verticesBuf = verticesBuf; - return ret; - } - - private static long createDescriptorPool(VkDevice device) { - // We need to tell the API the number of max. requested descriptors per type - VkDescriptorPoolSize.Buffer typeCounts = VkDescriptorPoolSize.calloc(1) - // This example only uses one descriptor type (uniform buffer) and only - // requests one descriptor of this type - .type(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) - .descriptorCount(1); - // For additional types you need to add new entries in the type count list - // E.g. for two combined image samplers : - // typeCounts[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - // typeCounts[1].descriptorCount = 2; - - // Create the global descriptor pool - // All descriptors used in this example are allocated from this pool - VkDescriptorPoolCreateInfo descriptorPoolInfo = VkDescriptorPoolCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO) - .pPoolSizes(typeCounts) - // Set the max. number of sets that can be requested - // Requesting descriptors beyond maxSets will result in an error - .maxSets(1); - - LongBuffer pDescriptorPool = memAllocLong(1); - int err = vkCreateDescriptorPool(device, descriptorPoolInfo, null, pDescriptorPool); - long descriptorPool = pDescriptorPool.get(0); - memFree(pDescriptorPool); - descriptorPoolInfo.free(); - typeCounts.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create descriptor pool: " + VKUtils.translateVulkanResult(err)); - } - return descriptorPool; - } - - private static class UboDescriptor { - long memory; - long buffer; - long offset; - long range; - } - - private static UboDescriptor createUniformBuffer(VkPhysicalDeviceMemoryProperties deviceMemoryProperties, VkDevice device) { - int err; - // Create a new buffer - VkBufferCreateInfo bufferInfo = VkBufferCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO) - .size(16 * 4) - .usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - LongBuffer pUniformDataVSBuffer = memAllocLong(1); - err = vkCreateBuffer(device, bufferInfo, null, pUniformDataVSBuffer); - long uniformDataVSBuffer = pUniformDataVSBuffer.get(0); - memFree(pUniformDataVSBuffer); - bufferInfo.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create UBO buffer: " + VKUtils.translateVulkanResult(err)); - } - - // Get memory requirements including size, alignment and memory type - VkMemoryRequirements memReqs = VkMemoryRequirements.calloc(); - vkGetBufferMemoryRequirements(device, uniformDataVSBuffer, memReqs); - long memSize = memReqs.size(); - int memoryTypeBits = memReqs.memoryTypeBits(); - memReqs.free(); - // Gets the appropriate memory type for this type of buffer allocation - // Only memory types that are visible to the host - IntBuffer pMemoryTypeIndex = memAllocInt(1); - getMemoryType(deviceMemoryProperties, memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, pMemoryTypeIndex); - int memoryTypeIndex = pMemoryTypeIndex.get(0); - memFree(pMemoryTypeIndex); - // Allocate memory for the uniform buffer - LongBuffer pUniformDataVSMemory = memAllocLong(1); - VkMemoryAllocateInfo allocInfo = VkMemoryAllocateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO) - .allocationSize(memSize) - .memoryTypeIndex(memoryTypeIndex); - err = vkAllocateMemory(device, allocInfo, null, pUniformDataVSMemory); - long uniformDataVSMemory = pUniformDataVSMemory.get(0); - memFree(pUniformDataVSMemory); - allocInfo.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to allocate UBO memory: " + VKUtils.translateVulkanResult(err)); - } - // Bind memory to buffer - err = vkBindBufferMemory(device, uniformDataVSBuffer, uniformDataVSMemory, 0); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to bind UBO memory: " + VKUtils.translateVulkanResult(err)); - } - - UboDescriptor ret = new UboDescriptor(); - ret.memory = uniformDataVSMemory; - ret.buffer = uniformDataVSBuffer; - ret.offset = 0L; - ret.range = 16 * 4; - - return ret; - } - - private static long createDescriptorSet(VkDevice device, long descriptorPool, long descriptorSetLayout, UboDescriptor uniformDataVSDescriptor) { - LongBuffer pDescriptorSetLayout = memAllocLong(1); - pDescriptorSetLayout.put(0, descriptorSetLayout); - VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO) - .descriptorPool(descriptorPool) - .pSetLayouts(pDescriptorSetLayout); - - LongBuffer pDescriptorSet = memAllocLong(1); - int err = vkAllocateDescriptorSets(device, allocInfo, pDescriptorSet); - long descriptorSet = pDescriptorSet.get(0); - memFree(pDescriptorSet); - allocInfo.free(); - memFree(pDescriptorSetLayout); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create descriptor set: " + VKUtils.translateVulkanResult(err)); - } - - // Update descriptor sets determining the shader binding points - // For every binding point used in a shader there needs to be one - // descriptor set matching that binding point - VkDescriptorBufferInfo.Buffer descriptor = VkDescriptorBufferInfo.calloc(1) - .buffer(uniformDataVSDescriptor.buffer) - .range(uniformDataVSDescriptor.range) - .offset(uniformDataVSDescriptor.offset); - // Binding 0 : Uniform buffer - VkWriteDescriptorSet.Buffer writeDescriptorSet = VkWriteDescriptorSet.calloc(1) - .sType(VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET) - .dstSet(descriptorSet) - .descriptorCount(1) - .descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) - .pBufferInfo(descriptor) - .dstBinding(0); // <- Binds this uniform buffer to binding point 0 - vkUpdateDescriptorSets(device, writeDescriptorSet, null); - writeDescriptorSet.free(); - descriptor.free(); - - return descriptorSet; - } - - private static long createDescriptorSetLayout(VkDevice device) { - int err; - // One binding for a UBO used in a vertex shader - VkDescriptorSetLayoutBinding.Buffer layoutBinding = VkDescriptorSetLayoutBinding.calloc(1) - .binding(0) // <- Binding 0 : Uniform buffer (Vertex shader) - .descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) - .descriptorCount(1) - .stageFlags(VK_SHADER_STAGE_VERTEX_BIT); - // Build a create-info struct to create the descriptor set layout - VkDescriptorSetLayoutCreateInfo descriptorLayout = VkDescriptorSetLayoutCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO) - .pBindings(layoutBinding); - - LongBuffer pDescriptorSetLayout = memAllocLong(1); - err = vkCreateDescriptorSetLayout(device, descriptorLayout, null, pDescriptorSetLayout); - long descriptorSetLayout = pDescriptorSetLayout.get(0); - memFree(pDescriptorSetLayout); - descriptorLayout.free(); - layoutBinding.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create descriptor set layout: " + VKUtils.translateVulkanResult(err)); - } - return descriptorSetLayout; - } - - private static class Pipeline { - long pipeline; - long layout; - } - - private static Pipeline createPipeline(VkDevice device, long renderPass, VkPipelineVertexInputStateCreateInfo vi, long descriptorSetLayout) throws IOException { - int err; - // Vertex input state - // Describes the topoloy used with this pipeline - VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = VkPipelineInputAssemblyStateCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO) - .topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); - - // Rasterization state - VkPipelineRasterizationStateCreateInfo rasterizationState = VkPipelineRasterizationStateCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO) - .polygonMode(VK_POLYGON_MODE_FILL) - .cullMode(VK_CULL_MODE_NONE) // <- VK_CULL_MODE_BACK_BIT would work here, too! - .frontFace(VK_FRONT_FACE_COUNTER_CLOCKWISE) - .lineWidth(1.0f); - - // Color blend state - // Describes blend modes and color masks - VkPipelineColorBlendAttachmentState.Buffer colorWriteMask = VkPipelineColorBlendAttachmentState.calloc(1) - .colorWriteMask(0xF); // <- RGBA - VkPipelineColorBlendStateCreateInfo colorBlendState = VkPipelineColorBlendStateCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO) - .pAttachments(colorWriteMask); - - // Viewport state - VkPipelineViewportStateCreateInfo viewportState = VkPipelineViewportStateCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO) - .viewportCount(1) // <- one viewport - .scissorCount(1); // <- one scissor rectangle - - // Enable dynamic states - // Describes the dynamic states to be used with this pipeline - // Dynamic states can be set even after the pipeline has been created - // So there is no need to create new pipelines just for changing - // a viewport's dimensions or a scissor box - IntBuffer pDynamicStates = memAllocInt(2); - pDynamicStates.put(VK_DYNAMIC_STATE_VIEWPORT).put(VK_DYNAMIC_STATE_SCISSOR).flip(); - VkPipelineDynamicStateCreateInfo dynamicState = VkPipelineDynamicStateCreateInfo.calloc() - // The dynamic state properties themselves are stored in the command buffer - .sType(VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO) - .pDynamicStates(pDynamicStates); - - // Depth and stencil state - // Describes depth and stenctil test and compare ops - VkPipelineDepthStencilStateCreateInfo depthStencilState = VkPipelineDepthStencilStateCreateInfo.calloc() - // No depth test/write and no stencil used - .sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO) - .depthTestEnable(true) - .depthWriteEnable(true) - .depthCompareOp(VK_COMPARE_OP_LESS_OR_EQUAL); - depthStencilState.back() - .failOp(VK_STENCIL_OP_KEEP) - .passOp(VK_STENCIL_OP_KEEP) - .compareOp(VK_COMPARE_OP_ALWAYS); - depthStencilState.front(depthStencilState.back()); - - // Multi sampling state - // No multi sampling used in this example - VkPipelineMultisampleStateCreateInfo multisampleState = VkPipelineMultisampleStateCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO) - .rasterizationSamples(VK_SAMPLE_COUNT_1_BIT); - - // Load shaders - VkPipelineShaderStageCreateInfo.Buffer shaderStages = VkPipelineShaderStageCreateInfo.calloc(2); - shaderStages.get(0).set(loadShader(device, "/vulkan/shaders/entityVertexShader.glsl", VK_SHADER_STAGE_VERTEX_BIT)); - shaderStages.get(1).set(loadShader(device, "/vulkan/shaders/entityFragmentShader.glsl", VK_SHADER_STAGE_FRAGMENT_BIT)); - - // Create the pipeline layout that is used to generate the rendering pipelines that - // are based on this descriptor set layout - LongBuffer pDescriptorSetLayout = memAllocLong(1).put(0, descriptorSetLayout); - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = VkPipelineLayoutCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO) - .pSetLayouts(pDescriptorSetLayout); - - LongBuffer pPipelineLayout = memAllocLong(1); - err = vkCreatePipelineLayout(device, pipelineLayoutCreateInfo, null, pPipelineLayout); - long layout = pPipelineLayout.get(0); - memFree(pPipelineLayout); - pipelineLayoutCreateInfo.free(); - memFree(pDescriptorSetLayout); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create pipeline layout: " + VKUtils.translateVulkanResult(err)); - } - - // Assign states - VkGraphicsPipelineCreateInfo.Buffer pipelineCreateInfo = VkGraphicsPipelineCreateInfo.calloc(1) - .sType(VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO) - .layout(layout) // <- the layout used for this pipeline (NEEDS TO BE SET! even though it is basically empty) - .renderPass(renderPass) // <- renderpass this pipeline is attached to - .pVertexInputState(vi) - .pInputAssemblyState(inputAssemblyState) - .pRasterizationState(rasterizationState) - .pColorBlendState(colorBlendState) - .pMultisampleState(multisampleState) - .pViewportState(viewportState) - .pDepthStencilState(depthStencilState) - .pStages(shaderStages) - .pDynamicState(dynamicState); - - // Create rendering pipeline - LongBuffer pPipelines = memAllocLong(1); - err = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, pipelineCreateInfo, null, pPipelines); - long pipeline = pPipelines.get(0); - shaderStages.free(); - multisampleState.free(); - depthStencilState.free(); - dynamicState.free(); - memFree(pDynamicStates); - viewportState.free(); - colorBlendState.free(); - colorWriteMask.free(); - rasterizationState.free(); - inputAssemblyState.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create pipeline: " + VKUtils.translateVulkanResult(err)); - } - - Pipeline ret = new Pipeline(); - ret.layout = layout; - ret.pipeline = pipeline; - return ret; - } - - private static VkCommandBuffer[] createRenderCommandBuffers(VkDevice device, long commandPool, long[] framebuffers, long renderPass, int width, int height, - Pipeline pipeline, long descriptorSet, long verticesBuf) { - // Create the render command buffers (one command buffer per framebuffer image) - VkCommandBufferAllocateInfo cmdBufAllocateInfo = VkCommandBufferAllocateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO) - .commandPool(commandPool) - .level(VK_COMMAND_BUFFER_LEVEL_PRIMARY) - .commandBufferCount(framebuffers.length); - PointerBuffer pCommandBuffer = memAllocPointer(framebuffers.length); - int err = vkAllocateCommandBuffers(device, cmdBufAllocateInfo, pCommandBuffer); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to allocate render command buffer: " + VKUtils.translateVulkanResult(err)); - } - VkCommandBuffer[] renderCommandBuffers = new VkCommandBuffer[framebuffers.length]; - for (int i = 0; i < framebuffers.length; i++) { - renderCommandBuffers[i] = new VkCommandBuffer(pCommandBuffer.get(i), device); - } - memFree(pCommandBuffer); - cmdBufAllocateInfo.free(); - - // Create the command buffer begin structure - VkCommandBufferBeginInfo cmdBufInfo = VkCommandBufferBeginInfo.calloc() - .sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); - - // Specify clear color (cornflower blue) - VkClearValue.Buffer clearValues = VkClearValue.calloc(2); - clearValues.get(0).color() - .float32(0, 100/255.0f) - .float32(1, 149/255.0f) - .float32(2, 237/255.0f) - .float32(3, 1.0f); - // Specify clear depth-stencil - clearValues.get(1).depthStencil().depth(1.0f).stencil(0); - - // Specify everything to begin a render pass - VkRenderPassBeginInfo renderPassBeginInfo = VkRenderPassBeginInfo.calloc() - .sType(VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO) - .renderPass(renderPass) - .pClearValues(clearValues); - VkRect2D renderArea = renderPassBeginInfo.renderArea(); - renderArea.offset().set(0, 0); - renderArea.extent().set(width, height); - - for (int i = 0; i < renderCommandBuffers.length; ++i) { - // Set target frame buffer - renderPassBeginInfo.framebuffer(framebuffers[i]); - - err = vkBeginCommandBuffer(renderCommandBuffers[i], cmdBufInfo); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to begin render command buffer: " + VKUtils.translateVulkanResult(err)); - } - - vkCmdBeginRenderPass(renderCommandBuffers[i], renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); - - // Update dynamic viewport state - VkViewport.Buffer viewport = VkViewport.calloc(1) - .height(height) - .width(width) - .minDepth(0.0f) - .maxDepth(1.0f); - vkCmdSetViewport(renderCommandBuffers[i], 0, viewport); - viewport.free(); - - // Update dynamic scissor state - VkRect2D.Buffer scissor = VkRect2D.calloc(1); - scissor.extent().set(width, height); - scissor.offset().set(0, 0); - vkCmdSetScissor(renderCommandBuffers[i], 0, scissor); - scissor.free(); - - // Bind descriptor sets describing shader binding points - LongBuffer descriptorSets = memAllocLong(1).put(0, descriptorSet); - vkCmdBindDescriptorSets(renderCommandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, descriptorSets, null); - memFree(descriptorSets); - - // Bind the rendering pipeline (including the shaders) - vkCmdBindPipeline(renderCommandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline); - - // Bind triangle vertices - LongBuffer offsets = memAllocLong(1); - offsets.put(0, 0L); - LongBuffer pBuffers = memAllocLong(1); - pBuffers.put(0, verticesBuf); - vkCmdBindVertexBuffers(renderCommandBuffers[i], 0, pBuffers, offsets); - memFree(pBuffers); - memFree(offsets); - - // Draw triangle - vkCmdDraw(renderCommandBuffers[i], 6, 1, 0, 0); - - vkCmdEndRenderPass(renderCommandBuffers[i]); - - err = vkEndCommandBuffer(renderCommandBuffers[i]); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to begin render command buffer: " + VKUtils.translateVulkanResult(err)); - } - } - renderPassBeginInfo.free(); - clearValues.free(); - cmdBufInfo.free(); - return renderCommandBuffers; - } - - private static void updateUbo(VkDevice device, UboDescriptor ubo, float angle) { //a UBO is a uniform buffer object - Matrix4f m = new Matrix4f() - .scale(1, -1, 1) // <- correcting viewport transformation (what Direct3D does, too) - .perspective((float) Math.toRadians(45.0f), (float) width / height, 0.1f, 10.0f, true) - .lookAt(0, 1, 3, - 0, 0, 0, - 0, 1, 0) - .rotateY(angle); - PointerBuffer pData = memAllocPointer(1); - int err = vkMapMemory(device, ubo.memory, 0, 16 * 4, 0, pData); - long data = pData.get(0); - memFree(pData); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to map UBO memory: " + VKUtils.translateVulkanResult(err)); - } - ByteBuffer matrixBuffer = memByteBuffer(data, 16 * 4); - m.get(matrixBuffer); - vkUnmapMemory(device, ubo.memory); - } - - /* - * All resources that must be reallocated on window resize. - */ - private static Swapchain swapchain; - private static long[] framebuffers; - private static VkCommandBuffer[] renderCommandBuffers; - private static int width, height; - private static DepthStencil depthStencil; - - public static void main(String[] args) throws IOException { - if (!glfwInit()) { - throw new RuntimeException("Failed to initialize GLFW"); - } - if (!glfwVulkanSupported()) { - throw new AssertionError("GLFW failed to find the Vulkan loader"); - } - - /* Look for instance extensions */ - PointerBuffer requiredExtensions = glfwGetRequiredInstanceExtensions(); - if (requiredExtensions == null) { - throw new AssertionError("Failed to find list of required Vulkan extensions"); - } - - // Create the Vulkan instance - final VkInstance instance = createInstance(requiredExtensions); - final VkDebugReportCallbackEXT debugCallback = new VkDebugReportCallbackEXT() { - public int invoke(int flags, int objectType, long object, long location, int messageCode, long pLayerPrefix, long pMessage, long pUserData) { - System.err.println("ERROR OCCURED: " + VkDebugReportCallbackEXT.getString(pMessage)); - return 0; - } - }; - final long debugCallbackHandle = setupDebugging(instance, VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, debugCallback); - final VkPhysicalDevice physicalDevice = getFirstPhysicalDevice(instance); - final DeviceAndGraphicsQueueFamily deviceAndGraphicsQueueFamily = createDeviceAndGetGraphicsQueueFamily(physicalDevice); - final VkDevice device = deviceAndGraphicsQueueFamily.device; - int queueFamilyIndex = deviceAndGraphicsQueueFamily.queueFamilyIndex; - final VkPhysicalDeviceMemoryProperties memoryProperties = deviceAndGraphicsQueueFamily.memoryProperties; - - // Create GLFW window - glfwDefaultWindowHints(); - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); - long window = glfwCreateWindow(800, 600, "GLFW Vulkan Demo", NULL, NULL); - GLFWKeyCallback keyCallback; - glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() { - public void invoke(long window, int key, int scancode, int action, int mods) { - if (action != GLFW_RELEASE) - return; - if (key == GLFW_KEY_ESCAPE) - glfwSetWindowShouldClose(window, true); - } - }); - LongBuffer pSurface = memAllocLong(1); - int err = glfwCreateWindowSurface(instance, window, null, pSurface); - final long surface = pSurface.get(0); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create surface: " + VKUtils.translateVulkanResult(err)); - } - - // Create static Vulkan resources - final ColorAndDepthFormatAndSpace colorAndDepthFormatAndSpace = getColorFormatAndSpace(physicalDevice, surface); - final long commandPool = createCommandPool(device, queueFamilyIndex); - final VkCommandBuffer setupCommandBuffer = createCommandBuffer(device, commandPool); - final VkQueue queue = createDeviceQueue(device, queueFamilyIndex); - final long renderPass = createRenderPass(device, colorAndDepthFormatAndSpace.colorFormat, colorAndDepthFormatAndSpace.depthFormat); - final long renderCommandPool = createCommandPool(device, queueFamilyIndex); - final Vertices vertices = createVertices(memoryProperties, device); - UboDescriptor uboDescriptor = createUniformBuffer(memoryProperties, device); - final long descriptorPool = createDescriptorPool(device); - final long descriptorSetLayout = createDescriptorSetLayout(device); - final long descriptorSet = createDescriptorSet(device, descriptorPool, descriptorSetLayout, uboDescriptor); - final Pipeline pipeline = createPipeline(device, renderPass, vertices.createInfo, descriptorSetLayout); - - final class SwapchainRecreator { - boolean mustRecreate = true; - void recreate() { - // Begin the setup command buffer (the one we will use for swapchain/framebuffer creation) - VkCommandBufferBeginInfo cmdBufInfo = VkCommandBufferBeginInfo.calloc() - .sType(VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO); - int err = vkBeginCommandBuffer(setupCommandBuffer, cmdBufInfo); - cmdBufInfo.free(); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to begin setup command buffer: " + VKUtils.translateVulkanResult(err)); - } - long oldChain = swapchain != null ? swapchain.swapchainHandle : VK_NULL_HANDLE; - // Create the swapchain (this will also add a memory barrier to initialize the framebuffer images) - swapchain = createSwapChain(device, physicalDevice, surface, oldChain, setupCommandBuffer, - width, height, colorAndDepthFormatAndSpace.colorFormat, colorAndDepthFormatAndSpace.colorSpace); - // Create depth-stencil image - depthStencil = createDepthStencil(device, memoryProperties, colorAndDepthFormatAndSpace.depthFormat, setupCommandBuffer); - err = vkEndCommandBuffer(setupCommandBuffer); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to end setup command buffer: " + VKUtils.translateVulkanResult(err)); - } - submitCommandBuffer(queue, setupCommandBuffer); - vkQueueWaitIdle(queue); - - if (framebuffers != null) { - for (int i = 0; i < framebuffers.length; i++) - vkDestroyFramebuffer(device, framebuffers[i], null); - } - framebuffers = createFramebuffers(device, swapchain, renderPass, width, height, depthStencil); - // Create render command buffers - if (renderCommandBuffers != null) { - vkResetCommandPool(device, renderCommandPool, VKUtils.VK_FLAGS_NONE); - } - renderCommandBuffers = createRenderCommandBuffers(device, renderCommandPool, framebuffers, renderPass, width, height, pipeline, descriptorSet, - vertices.verticesBuf); - - mustRecreate = false; - } - } - final SwapchainRecreator swapchainRecreator = new SwapchainRecreator(); - - // Handle canvas resize - GLFWFramebufferSizeCallback framebufferSizeCallback = new GLFWFramebufferSizeCallback() { - public void invoke(long window, int width, int height) { - if (width <= 0 || height <= 0) - return; - swapchainRecreator.mustRecreate = true; - VulkanStarter.width = width; - VulkanStarter.height = height; - } - }; - glfwSetFramebufferSizeCallback(window, framebufferSizeCallback); - glfwShowWindow(window); - - // Pre-allocate everything needed in the render loop - - IntBuffer pImageIndex = memAllocInt(1); - int currentBuffer = 0; - PointerBuffer pCommandBuffers = memAllocPointer(1); - LongBuffer pSwapchains = memAllocLong(1); - LongBuffer pImageAcquiredSemaphore = memAllocLong(1); - LongBuffer pRenderCompleteSemaphore = memAllocLong(1); - - // Info struct to create a semaphore - VkSemaphoreCreateInfo semaphoreCreateInfo = VkSemaphoreCreateInfo.calloc() - .sType(VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO); - - // Info struct to submit a command buffer which will wait on the semaphore - IntBuffer pWaitDstStageMask = memAllocInt(1); - pWaitDstStageMask.put(0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - VkSubmitInfo submitInfo = VkSubmitInfo.calloc() - .sType(VK_STRUCTURE_TYPE_SUBMIT_INFO) - .waitSemaphoreCount(pImageAcquiredSemaphore.remaining()) - .pWaitSemaphores(pImageAcquiredSemaphore) - .pWaitDstStageMask(pWaitDstStageMask) - .pCommandBuffers(pCommandBuffers) - .pSignalSemaphores(pRenderCompleteSemaphore); - - // Info struct to present the current swapchain image to the display - VkPresentInfoKHR presentInfo = VkPresentInfoKHR.calloc() - .sType(VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) - .pWaitSemaphores(pRenderCompleteSemaphore) - .swapchainCount(pSwapchains.remaining()) - .pSwapchains(pSwapchains) - .pImageIndices(pImageIndex) - .pResults(null); - - // The render loop - long lastTime = System.nanoTime(); - float time = 0.0f; - while (!glfwWindowShouldClose(window)) { - // Handle window messages. Resize events happen exactly here. - // So it is safe to use the new swapchain images and framebuffers afterwards. - glfwPollEvents(); - if (swapchainRecreator.mustRecreate) - swapchainRecreator.recreate(); - - // Create a semaphore to wait for the swapchain to acquire the next image - err = vkCreateSemaphore(device, semaphoreCreateInfo, null, pImageAcquiredSemaphore); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create image acquired semaphore: " + VKUtils.translateVulkanResult(err)); - } - - // Create a semaphore to wait for the render to complete, before presenting - err = vkCreateSemaphore(device, semaphoreCreateInfo, null, pRenderCompleteSemaphore); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to create render complete semaphore: " + VKUtils.translateVulkanResult(err)); - } - - // Get next image from the swap chain (back/front buffer). - // This will setup the imageAquiredSemaphore to be signalled when the operation is complete - err = vkAcquireNextImageKHR(device, swapchain.swapchainHandle, UINT64_MAX, pImageAcquiredSemaphore.get(0), VK_NULL_HANDLE, pImageIndex); - currentBuffer = pImageIndex.get(0); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to acquire next swapchain image: " + VKUtils.translateVulkanResult(err)); - } - - // Select the command buffer for the current framebuffer image/attachment - pCommandBuffers.put(0, renderCommandBuffers[currentBuffer]); - - // Update UBO - long thisTime = System.nanoTime(); - time += (thisTime - lastTime) / 1E9f; - lastTime = thisTime; - updateUbo(device, uboDescriptor, time); - - // Submit to the graphics queue - err = vkQueueSubmit(queue, submitInfo, VK_NULL_HANDLE); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to submit render queue: " + VKUtils.translateVulkanResult(err)); - } - - // Present the current buffer to the swap chain - // This will display the image - pSwapchains.put(0, swapchain.swapchainHandle); - err = vkQueuePresentKHR(queue, presentInfo); - if (err != VK_SUCCESS) { - throw new AssertionError("Failed to present the swapchain image: " + VKUtils.translateVulkanResult(err)); - } - // Create and submit post present barrier - vkQueueWaitIdle(queue); - - // Destroy this semaphore (we will create a new one in the next frame) - vkDestroySemaphore(device, pImageAcquiredSemaphore.get(0), null); - vkDestroySemaphore(device, pRenderCompleteSemaphore.get(0), null); - } - presentInfo.free(); - memFree(pWaitDstStageMask); - submitInfo.free(); - memFree(pImageAcquiredSemaphore); - memFree(pRenderCompleteSemaphore); - semaphoreCreateInfo.free(); - memFree(pSwapchains); - memFree(pCommandBuffers); - - vkDestroyDebugReportCallbackEXT(instance, debugCallbackHandle, null); - - framebufferSizeCallback.free(); - keyCallback.free(); - glfwDestroyWindow(window); - glfwTerminate(); - - // We don't bother disposing of all Vulkan resources. - // Let the OS process manager take care of it. - } - -} \ No newline at end of file diff --git a/src/main/java/com/github/hydos/ginger/engine/common/io/Window.java b/src/main/java/com/github/hydos/ginger/engine/common/io/Window.java index 4784b22..cfc09de 100644 --- a/src/main/java/com/github/hydos/ginger/engine/common/io/Window.java +++ b/src/main/java/com/github/hydos/ginger/engine/common/io/Window.java @@ -69,6 +69,13 @@ public class Window }else if (renderAPI == RenderAPI.Vulkan) GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE); +<<<<<<< Upstream, based on branch 'liteCraft' of https://github.com/halotroop/Ginger3D.git +======= + GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4); + GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 6); + GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE); + GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GL11.GL_TRUE); +>>>>>>> 2023b14 OpenGL 4.6 YeS GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, GLFW.GLFW_TRUE); GLFWVidMode vidmode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor()); window = GLFW.glfwCreateWindow(actualWidth, actualHeight, title, (fullscreen) ? GLFW.glfwGetPrimaryMonitor() : 0, getWindow()); @@ -89,7 +96,11 @@ public class Window oldWindowHeight = getHeight(); } +<<<<<<< Upstream, based on branch 'liteCraft' of https://github.com/halotroop/Ginger3D.git public static void create(int width, int height, String title, int fpsCap, RenderAPI api) +======= + public static void create(int width, int height, String title, float fpsCap) +>>>>>>> 2023b14 OpenGL 4.6 YeS { Window.width = width / 2; Window.height = height / 2;