From e5b2fbf25ddd4810f4f6ae96d812117f9d4254ed Mon Sep 17 00:00:00 2001
From: hayden v <haydenv06@gmail.com>
Date: Tue, 3 Mar 2020 11:10:59 +1000
Subject: [PATCH] moved around shader code and other vulkan stuff

---
 .classpath                                    |   2 +-
 .../github/hydos/ginger/VulkanStarter.java    | 411 ++++++++----------
 .../vulkan/{utils => }/VKConstants.java       |   2 +-
 .../engine/vulkan/shaders/Pipeline.java       | 166 +++++++
 .../vulkan/shaders/VKShaderManager.java       |  48 ++
 .../vulkan/utils/VKDeviceProperties.java      |  98 +++++
 .../ginger/engine/vulkan/utils/VKLoader.java  |   2 +
 .../ginger/engine/vulkan/utils/VKUtils.java   |  68 ++-
 .../vulkan/utils/VulkanFuncWrapper.java       |   7 +-
 9 files changed, 560 insertions(+), 244 deletions(-)
 rename src/main/java/com/github/hydos/ginger/engine/vulkan/{utils => }/VKConstants.java (88%)
 create mode 100644 src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/Pipeline.java
 create mode 100644 src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderManager.java
 create mode 100644 src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKDeviceProperties.java

diff --git a/.classpath b/.classpath
index febc371..a93fc90 100644
--- a/.classpath
+++ b/.classpath
@@ -5,7 +5,7 @@
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-13">
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
 		<attributes>
 			<attribute name="module" value="true"/>
 			<attribute name="maven.pomderived" value="true"/>
diff --git a/src/main/java/com/github/hydos/ginger/VulkanStarter.java b/src/main/java/com/github/hydos/ginger/VulkanStarter.java
index 4dc3d3a..e85842e 100644
--- a/src/main/java/com/github/hydos/ginger/VulkanStarter.java
+++ b/src/main/java/com/github/hydos/ginger/VulkanStarter.java
@@ -1,25 +1,194 @@
 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.VK10.*;
+import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE;
+import static org.lwjgl.glfw.GLFW.GLFW_RELEASE;
+import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
+import static org.lwjgl.glfw.GLFW.glfwPollEvents;
+import static org.lwjgl.glfw.GLFW.glfwSetFramebufferSizeCallback;
+import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback;
+import static org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose;
+import static org.lwjgl.glfw.GLFW.glfwShowWindow;
+import static org.lwjgl.glfw.GLFW.glfwTerminate;
+import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
+import static org.lwjgl.glfw.GLFWVulkan.glfwCreateWindowSurface;
+import static org.lwjgl.glfw.GLFWVulkan.glfwGetRequiredInstanceExtensions;
+import static org.lwjgl.system.MemoryUtil.NULL;
+import static org.lwjgl.system.MemoryUtil.memAddress;
+import static org.lwjgl.system.MemoryUtil.memAlloc;
+import static org.lwjgl.system.MemoryUtil.memAllocInt;
+import static org.lwjgl.system.MemoryUtil.memAllocLong;
+import static org.lwjgl.system.MemoryUtil.memAllocPointer;
+import static org.lwjgl.system.MemoryUtil.memByteBuffer;
+import static org.lwjgl.system.MemoryUtil.memCopy;
+import static org.lwjgl.system.MemoryUtil.memFree;
+import static org.lwjgl.system.MemoryUtil.memUTF8;
+import static org.lwjgl.vulkan.EXTDebugReport.VK_DEBUG_REPORT_ERROR_BIT_EXT;
+import static org.lwjgl.vulkan.EXTDebugReport.VK_DEBUG_REPORT_WARNING_BIT_EXT;
+import static org.lwjgl.vulkan.EXTDebugReport.vkDestroyDebugReportCallbackEXT;
+import static org.lwjgl.vulkan.KHRSurface.VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+import static org.lwjgl.vulkan.KHRSurface.VK_PRESENT_MODE_FIFO_KHR;
+import static org.lwjgl.vulkan.KHRSurface.VK_PRESENT_MODE_IMMEDIATE_KHR;
+import static org.lwjgl.vulkan.KHRSurface.VK_PRESENT_MODE_MAILBOX_KHR;
+import static org.lwjgl.vulkan.KHRSurface.VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+import static org.lwjgl.vulkan.KHRSurface.vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
+import static org.lwjgl.vulkan.KHRSurface.vkGetPhysicalDeviceSurfaceFormatsKHR;
+import static org.lwjgl.vulkan.KHRSurface.vkGetPhysicalDeviceSurfacePresentModesKHR;
+import static org.lwjgl.vulkan.KHRSurface.vkGetPhysicalDeviceSurfaceSupportKHR;
+import static org.lwjgl.vulkan.KHRSwapchain.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+import static org.lwjgl.vulkan.KHRSwapchain.VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+import static org.lwjgl.vulkan.KHRSwapchain.VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+import static org.lwjgl.vulkan.KHRSwapchain.vkAcquireNextImageKHR;
+import static org.lwjgl.vulkan.KHRSwapchain.vkCreateSwapchainKHR;
+import static org.lwjgl.vulkan.KHRSwapchain.vkDestroySwapchainKHR;
+import static org.lwjgl.vulkan.KHRSwapchain.vkGetSwapchainImagesKHR;
+import static org.lwjgl.vulkan.KHRSwapchain.vkQueuePresentKHR;
+import static org.lwjgl.vulkan.VK10.VK_ATTACHMENT_LOAD_OP_CLEAR;
+import static org.lwjgl.vulkan.VK10.VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+import static org.lwjgl.vulkan.VK10.VK_ATTACHMENT_STORE_OP_DONT_CARE;
+import static org.lwjgl.vulkan.VK10.VK_ATTACHMENT_STORE_OP_STORE;
+import static org.lwjgl.vulkan.VK10.VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+import static org.lwjgl.vulkan.VK10.VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+import static org.lwjgl.vulkan.VK10.VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+import static org.lwjgl.vulkan.VK10.VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+import static org.lwjgl.vulkan.VK10.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+import static org.lwjgl.vulkan.VK10.VK_FORMAT_B8G8R8A8_UNORM;
+import static org.lwjgl.vulkan.VK10.VK_FORMAT_D16_UNORM;
+import static org.lwjgl.vulkan.VK10.VK_FORMAT_D16_UNORM_S8_UINT;
+import static org.lwjgl.vulkan.VK10.VK_FORMAT_D24_UNORM_S8_UINT;
+import static org.lwjgl.vulkan.VK10.VK_FORMAT_D32_SFLOAT;
+import static org.lwjgl.vulkan.VK10.VK_FORMAT_D32_SFLOAT_S8_UINT;
+import static org.lwjgl.vulkan.VK10.VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
+import static org.lwjgl.vulkan.VK10.VK_FORMAT_R32G32B32_SFLOAT;
+import static org.lwjgl.vulkan.VK10.VK_FORMAT_UNDEFINED;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_ASPECT_COLOR_BIT;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_ASPECT_DEPTH_BIT;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_ASPECT_STENCIL_BIT;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_LAYOUT_UNDEFINED;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_TILING_OPTIMAL;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_TYPE_2D;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+import static org.lwjgl.vulkan.VK10.VK_IMAGE_VIEW_TYPE_2D;
+import static org.lwjgl.vulkan.VK10.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+import static org.lwjgl.vulkan.VK10.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+import static org.lwjgl.vulkan.VK10.VK_NULL_HANDLE;
+import static org.lwjgl.vulkan.VK10.VK_PIPELINE_BIND_POINT_GRAPHICS;
+import static org.lwjgl.vulkan.VK10.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+import static org.lwjgl.vulkan.VK10.VK_QUEUE_GRAPHICS_BIT;
+import static org.lwjgl.vulkan.VK10.VK_SAMPLE_COUNT_1_BIT;
+import static org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_VERTEX_BIT;
+import static org.lwjgl.vulkan.VK10.VK_SHARING_MODE_EXCLUSIVE;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_SUBMIT_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+import static org.lwjgl.vulkan.VK10.VK_SUCCESS;
+import static org.lwjgl.vulkan.VK10.VK_TRUE;
+import static org.lwjgl.vulkan.VK10.VK_VERTEX_INPUT_RATE_VERTEX;
+import static org.lwjgl.vulkan.VK10.vkAllocateCommandBuffers;
+import static org.lwjgl.vulkan.VK10.vkAllocateDescriptorSets;
+import static org.lwjgl.vulkan.VK10.vkAllocateMemory;
+import static org.lwjgl.vulkan.VK10.vkBeginCommandBuffer;
+import static org.lwjgl.vulkan.VK10.vkBindBufferMemory;
+import static org.lwjgl.vulkan.VK10.vkBindImageMemory;
+import static org.lwjgl.vulkan.VK10.vkCreateBuffer;
+import static org.lwjgl.vulkan.VK10.vkCreateCommandPool;
+import static org.lwjgl.vulkan.VK10.vkCreateDescriptorPool;
+import static org.lwjgl.vulkan.VK10.vkCreateDescriptorSetLayout;
+import static org.lwjgl.vulkan.VK10.vkCreateFramebuffer;
+import static org.lwjgl.vulkan.VK10.vkCreateImage;
+import static org.lwjgl.vulkan.VK10.vkCreateImageView;
+import static org.lwjgl.vulkan.VK10.vkCreateRenderPass;
+import static org.lwjgl.vulkan.VK10.vkCreateSemaphore;
+import static org.lwjgl.vulkan.VK10.vkDestroyFramebuffer;
+import static org.lwjgl.vulkan.VK10.vkDestroySemaphore;
+import static org.lwjgl.vulkan.VK10.vkEndCommandBuffer;
+import static org.lwjgl.vulkan.VK10.vkGetBufferMemoryRequirements;
+import static org.lwjgl.vulkan.VK10.vkGetDeviceQueue;
+import static org.lwjgl.vulkan.VK10.vkGetImageMemoryRequirements;
+import static org.lwjgl.vulkan.VK10.vkGetPhysicalDeviceFormatProperties;
+import static org.lwjgl.vulkan.VK10.vkGetPhysicalDeviceQueueFamilyProperties;
+import static org.lwjgl.vulkan.VK10.vkMapMemory;
+import static org.lwjgl.vulkan.VK10.vkQueueSubmit;
+import static org.lwjgl.vulkan.VK10.vkQueueWaitIdle;
+import static org.lwjgl.vulkan.VK10.vkResetCommandPool;
+import static org.lwjgl.vulkan.VK10.vkUnmapMemory;
+import static org.lwjgl.vulkan.VK10.vkUpdateDescriptorSets;
 
 import java.io.IOException;
-import java.nio.*;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
 
 import org.joml.Matrix4f;
 import org.lwjgl.PointerBuffer;
-import org.lwjgl.glfw.*;
-import org.lwjgl.vulkan.*;
+import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
+import org.lwjgl.glfw.GLFWKeyCallback;
+import org.lwjgl.vulkan.VkAttachmentDescription;
+import org.lwjgl.vulkan.VkAttachmentReference;
+import org.lwjgl.vulkan.VkBufferCreateInfo;
+import org.lwjgl.vulkan.VkCommandBuffer;
+import org.lwjgl.vulkan.VkCommandBufferAllocateInfo;
+import org.lwjgl.vulkan.VkCommandBufferBeginInfo;
+import org.lwjgl.vulkan.VkCommandPoolCreateInfo;
+import org.lwjgl.vulkan.VkDescriptorBufferInfo;
+import org.lwjgl.vulkan.VkDescriptorPoolCreateInfo;
+import org.lwjgl.vulkan.VkDescriptorPoolSize;
+import org.lwjgl.vulkan.VkDescriptorSetAllocateInfo;
+import org.lwjgl.vulkan.VkDescriptorSetLayoutBinding;
+import org.lwjgl.vulkan.VkDescriptorSetLayoutCreateInfo;
+import org.lwjgl.vulkan.VkDevice;
+import org.lwjgl.vulkan.VkExtent2D;
+import org.lwjgl.vulkan.VkFormatProperties;
+import org.lwjgl.vulkan.VkFramebufferCreateInfo;
+import org.lwjgl.vulkan.VkImageCreateInfo;
+import org.lwjgl.vulkan.VkImageViewCreateInfo;
+import org.lwjgl.vulkan.VkInstance;
+import org.lwjgl.vulkan.VkMemoryAllocateInfo;
+import org.lwjgl.vulkan.VkMemoryRequirements;
+import org.lwjgl.vulkan.VkPhysicalDevice;
+import org.lwjgl.vulkan.VkPhysicalDeviceMemoryProperties;
+import org.lwjgl.vulkan.VkPipelineShaderStageCreateInfo;
+import org.lwjgl.vulkan.VkPipelineVertexInputStateCreateInfo;
+import org.lwjgl.vulkan.VkPresentInfoKHR;
+import org.lwjgl.vulkan.VkQueue;
+import org.lwjgl.vulkan.VkQueueFamilyProperties;
+import org.lwjgl.vulkan.VkRenderPassCreateInfo;
+import org.lwjgl.vulkan.VkSemaphoreCreateInfo;
+import org.lwjgl.vulkan.VkSubmitInfo;
+import org.lwjgl.vulkan.VkSubpassDescription;
+import org.lwjgl.vulkan.VkSurfaceCapabilitiesKHR;
+import org.lwjgl.vulkan.VkSurfaceFormatKHR;
+import org.lwjgl.vulkan.VkSwapchainCreateInfoKHR;
+import org.lwjgl.vulkan.VkVertexInputAttributeDescription;
+import org.lwjgl.vulkan.VkVertexInputBindingDescription;
+import org.lwjgl.vulkan.VkWriteDescriptorSet;
 
 import com.github.hydos.ginger.engine.common.info.RenderAPI;
 import com.github.hydos.ginger.engine.common.io.Window;
-import com.github.hydos.ginger.engine.vulkan.utils.*;
-import com.github.hydos.ginger.engine.vulkan.utils.VKUtils.Pipeline;
+import com.github.hydos.ginger.engine.vulkan.VKConstants;
+import com.github.hydos.ginger.engine.vulkan.shaders.Pipeline;
+import com.github.hydos.ginger.engine.vulkan.shaders.VKShaderManager;
+import com.github.hydos.ginger.engine.vulkan.utils.VKDeviceProperties;
+import com.github.hydos.ginger.engine.vulkan.utils.VKLoader;
+import com.github.hydos.ginger.engine.vulkan.utils.VKUtils;
 /**
  * 
  * @author hydos06
@@ -28,80 +197,6 @@ import com.github.hydos.ginger.engine.vulkan.utils.VKUtils.Pipeline;
  */
 public class VulkanStarter
 {
-	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(VKConstants.layers.length);
-		for (int i = 0; VKConstants.debug && i < VKConstants.layers.length; i++)
-			ppEnabledLayerNames.put(VKConstants.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)
 	{
@@ -562,32 +657,6 @@ public class VulkanStarter
 		{ 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;
@@ -849,116 +918,6 @@ public class VulkanStarter
 		return descriptorSetLayout;
 	}
 
-	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 void updateUbo(VkDevice device, UboDescriptor ubo, float angle)
 	{ //a UBO is a uniform buffer object
 		Matrix4f m = new Matrix4f()
@@ -998,8 +957,8 @@ public class VulkanStarter
 		final VkInstance instance = VKLoader.createInstance(requiredExtensions);
 		VKUtils.setupVulkanDebugCallback();
 		final long debugCallbackHandle = VKUtils.startVulkanDebugging(instance, VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, VKConstants.debugCallback);
-		final VkPhysicalDevice physicalDevice = getFirstPhysicalDevice(instance);
-		final DeviceAndGraphicsQueueFamily deviceAndGraphicsQueueFamily = createDeviceAndGetGraphicsQueueFamily(physicalDevice);
+		final VkPhysicalDevice physicalDevice = VKDeviceProperties.getFirstPhysicalDevice(instance);
+		final VKDeviceProperties deviceAndGraphicsQueueFamily = VKDeviceProperties.initDeviceProperties(physicalDevice);
 		final VkDevice device = deviceAndGraphicsQueueFamily.device;
 		int queueFamilyIndex = deviceAndGraphicsQueueFamily.queueFamilyIndex;
 		final VkPhysicalDeviceMemoryProperties memoryProperties = deviceAndGraphicsQueueFamily.memoryProperties;
@@ -1026,12 +985,12 @@ public class VulkanStarter
 		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);
+		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 Pipeline pipeline = Pipeline.createPipeline(device, renderPass, vertices.createInfo, descriptorSetLayout);
 		final class SwapchainRecreator
 		{
 			boolean mustRecreate = true;
diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKConstants.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/VKConstants.java
similarity index 88%
rename from src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKConstants.java
rename to src/main/java/com/github/hydos/ginger/engine/vulkan/VKConstants.java
index 07987b2..c1d7647 100644
--- a/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKConstants.java
+++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/VKConstants.java
@@ -1,4 +1,4 @@
-package com.github.hydos.ginger.engine.vulkan.utils;
+package com.github.hydos.ginger.engine.vulkan;
 
 import java.nio.ByteBuffer;
 
diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/Pipeline.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/Pipeline.java
new file mode 100644
index 0000000..ee04e31
--- /dev/null
+++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/Pipeline.java
@@ -0,0 +1,166 @@
+package com.github.hydos.ginger.engine.vulkan.shaders;
+
+import static org.lwjgl.system.MemoryUtil.memAllocInt;
+import static org.lwjgl.system.MemoryUtil.memAllocLong;
+import static org.lwjgl.system.MemoryUtil.memFree;
+import static org.lwjgl.vulkan.VK10.VK_COMPARE_OP_ALWAYS;
+import static org.lwjgl.vulkan.VK10.VK_COMPARE_OP_LESS_OR_EQUAL;
+import static org.lwjgl.vulkan.VK10.VK_CULL_MODE_NONE;
+import static org.lwjgl.vulkan.VK10.VK_DYNAMIC_STATE_SCISSOR;
+import static org.lwjgl.vulkan.VK10.VK_DYNAMIC_STATE_VIEWPORT;
+import static org.lwjgl.vulkan.VK10.VK_FRONT_FACE_COUNTER_CLOCKWISE;
+import static org.lwjgl.vulkan.VK10.VK_NULL_HANDLE;
+import static org.lwjgl.vulkan.VK10.VK_POLYGON_MODE_FILL;
+import static org.lwjgl.vulkan.VK10.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+import static org.lwjgl.vulkan.VK10.VK_SAMPLE_COUNT_1_BIT;
+import static org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_FRAGMENT_BIT;
+import static org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_VERTEX_BIT;
+import static org.lwjgl.vulkan.VK10.VK_STENCIL_OP_KEEP;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_SUCCESS;
+import static org.lwjgl.vulkan.VK10.vkCreateGraphicsPipelines;
+import static org.lwjgl.vulkan.VK10.vkCreatePipelineLayout;
+
+import java.io.IOException;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+
+import org.lwjgl.vulkan.VkDevice;
+import org.lwjgl.vulkan.VkGraphicsPipelineCreateInfo;
+import org.lwjgl.vulkan.VkPipelineColorBlendAttachmentState;
+import org.lwjgl.vulkan.VkPipelineColorBlendStateCreateInfo;
+import org.lwjgl.vulkan.VkPipelineDepthStencilStateCreateInfo;
+import org.lwjgl.vulkan.VkPipelineDynamicStateCreateInfo;
+import org.lwjgl.vulkan.VkPipelineInputAssemblyStateCreateInfo;
+import org.lwjgl.vulkan.VkPipelineLayoutCreateInfo;
+import org.lwjgl.vulkan.VkPipelineMultisampleStateCreateInfo;
+import org.lwjgl.vulkan.VkPipelineRasterizationStateCreateInfo;
+import org.lwjgl.vulkan.VkPipelineShaderStageCreateInfo;
+import org.lwjgl.vulkan.VkPipelineVertexInputStateCreateInfo;
+import org.lwjgl.vulkan.VkPipelineViewportStateCreateInfo;
+
+import com.github.hydos.ginger.engine.vulkan.utils.VKUtils;
+
+public class Pipeline
+{
+	public long pipeline;
+	public long layout;
+	
+	public 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(VKShaderManager.loadShader(device, "/vulkan/shaders/entityVertexShader.glsl", VK_SHADER_STAGE_VERTEX_BIT));
+		shaderStages.get(1).set(VKShaderManager.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)); }
+		com.github.hydos.ginger.engine.vulkan.shaders.Pipeline ret = new com.github.hydos.ginger.engine.vulkan.shaders.Pipeline();
+		ret.layout = layout;
+		ret.pipeline = pipeline;
+		return ret;
+	}
+}
diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderManager.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderManager.java
new file mode 100644
index 0000000..51e4b63
--- /dev/null
+++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/shaders/VKShaderManager.java
@@ -0,0 +1,48 @@
+package com.github.hydos.ginger.engine.vulkan.shaders;
+
+import static org.lwjgl.system.MemoryUtil.memAllocLong;
+import static org.lwjgl.system.MemoryUtil.memFree;
+import static org.lwjgl.system.MemoryUtil.memUTF8;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+import static org.lwjgl.vulkan.VK10.VK_SUCCESS;
+import static org.lwjgl.vulkan.VK10.vkCreateShaderModule;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.LongBuffer;
+
+import org.lwjgl.vulkan.VkDevice;
+import org.lwjgl.vulkan.VkPipelineShaderStageCreateInfo;
+import org.lwjgl.vulkan.VkShaderModuleCreateInfo;
+
+import com.github.hydos.ginger.engine.vulkan.utils.VKUtils;
+
+public class VKShaderManager {
+	
+	public 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(VKShaderManager.loadShader(classPath, device, stage))
+			.pName(memUTF8("main"));
+		return shaderStage;
+	}
+	
+	public 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;
+	}
+}
diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKDeviceProperties.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKDeviceProperties.java
new file mode 100644
index 0000000..d9f0c16
--- /dev/null
+++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKDeviceProperties.java
@@ -0,0 +1,98 @@
+package com.github.hydos.ginger.engine.vulkan.utils;
+
+import static org.lwjgl.system.MemoryUtil.memAllocFloat;
+import static org.lwjgl.system.MemoryUtil.memAllocInt;
+import static org.lwjgl.system.MemoryUtil.memAllocPointer;
+import static org.lwjgl.system.MemoryUtil.memFree;
+import static org.lwjgl.system.MemoryUtil.memUTF8;
+import static org.lwjgl.vulkan.KHRSwapchain.VK_KHR_SWAPCHAIN_EXTENSION_NAME;
+
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.PointerBuffer;
+import org.lwjgl.vulkan.VK12;
+import org.lwjgl.vulkan.VkDevice;
+import org.lwjgl.vulkan.VkDeviceCreateInfo;
+import org.lwjgl.vulkan.VkDeviceQueueCreateInfo;
+import org.lwjgl.vulkan.VkInstance;
+import org.lwjgl.vulkan.VkPhysicalDevice;
+import org.lwjgl.vulkan.VkPhysicalDeviceMemoryProperties;
+import org.lwjgl.vulkan.VkQueueFamilyProperties;
+
+import com.github.hydos.ginger.engine.vulkan.VKConstants;
+
+public class VKDeviceProperties {
+	public VkDevice device;
+	public int queueFamilyIndex;
+	public VkPhysicalDeviceMemoryProperties memoryProperties;
+	
+	public static VkPhysicalDevice getFirstPhysicalDevice(VkInstance instance)
+	{
+		IntBuffer pPhysicalDeviceCount = memAllocInt(1);
+		int err = VK12.vkEnumeratePhysicalDevices(instance, pPhysicalDeviceCount, null);
+		if (err != VK12.VK_SUCCESS)
+		{ throw new AssertionError("Failed to get number of physical devices: " + VKUtils.translateVulkanResult(err)); }
+		PointerBuffer pPhysicalDevices = memAllocPointer(pPhysicalDeviceCount.get(0));
+		err = VK12.vkEnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
+		long physicalDevice = pPhysicalDevices.get(0);
+		memFree(pPhysicalDeviceCount);
+		memFree(pPhysicalDevices);
+		if (err != VK12.VK_SUCCESS)
+		{ throw new AssertionError("Failed to get physical devices: " + VKUtils.translateVulkanResult(err)); }
+		return new VkPhysicalDevice(physicalDevice, instance);
+	}
+	
+	public static VKDeviceProperties initDeviceProperties(VkPhysicalDevice physicalDevice)
+	{
+		IntBuffer pQueueFamilyPropertyCount = memAllocInt(1);
+		VK12.vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, null);
+		int queueCount = pQueueFamilyPropertyCount.get(0);
+		VkQueueFamilyProperties.Buffer queueProps = VkQueueFamilyProperties.calloc(queueCount);
+		VK12.vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, queueProps);
+		memFree(pQueueFamilyPropertyCount);
+		int graphicsQueueFamilyIndex;
+		for (graphicsQueueFamilyIndex = 0; graphicsQueueFamilyIndex < queueCount; graphicsQueueFamilyIndex++)
+		{ if ((queueProps.get(graphicsQueueFamilyIndex).queueFlags() & VK12.VK_QUEUE_GRAPHICS_BIT) != 0)
+			break; }
+		queueProps.free();
+		FloatBuffer pQueuePriorities = memAllocFloat(1).put(0.0f);
+		pQueuePriorities.flip();
+		VkDeviceQueueCreateInfo.Buffer queueCreateInfo = VkDeviceQueueCreateInfo.calloc(1)
+			.sType(VK12.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(VKConstants.layers.length);
+		for (int i = 0; VKConstants.debug && i < VKConstants.layers.length; i++)
+			ppEnabledLayerNames.put(VKConstants.layers[i]);
+		ppEnabledLayerNames.flip();
+		VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.calloc()
+			.sType(VK12.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
+			.pQueueCreateInfos(queueCreateInfo)
+			.ppEnabledExtensionNames(extensions)
+			.ppEnabledLayerNames(ppEnabledLayerNames);
+		PointerBuffer pDevice = memAllocPointer(1);
+		int err = VK12.vkCreateDevice(physicalDevice, deviceCreateInfo, null, pDevice);
+		long device = pDevice.get(0);
+		memFree(pDevice);
+		if (err != VK12.VK_SUCCESS)
+		{ throw new AssertionError("Failed to create device: " + VKUtils.translateVulkanResult(err)); }
+		VkPhysicalDeviceMemoryProperties memoryProperties = VkPhysicalDeviceMemoryProperties.calloc();
+		VK12.vkGetPhysicalDeviceMemoryProperties(physicalDevice, memoryProperties);
+		VKDeviceProperties ret = new VKDeviceProperties();
+		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;
+	}
+}
diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKLoader.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKLoader.java
index 880298d..58c3e64 100644
--- a/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKLoader.java
+++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKLoader.java
@@ -10,6 +10,8 @@ import java.nio.ByteBuffer;
 import org.lwjgl.PointerBuffer;
 import org.lwjgl.vulkan.*;
 
+import com.github.hydos.ginger.engine.vulkan.VKConstants;
+
 /** @author hydos
  *         used to load vulkan related objects such as textures */
 public class VKLoader
diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKUtils.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKUtils.java
index 6a7fa22..f11cc66 100644
--- a/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKUtils.java
+++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VKUtils.java
@@ -1,21 +1,65 @@
 package com.github.hydos.ginger.engine.vulkan.utils;
 
-import static org.lwjgl.system.MemoryUtil.*;
-import static org.lwjgl.util.shaderc.Shaderc.*;
-import static org.lwjgl.vulkan.EXTDebugReport.*;
-import static org.lwjgl.vulkan.KHRSurface.*;
+import static org.lwjgl.system.MemoryUtil.memAllocLong;
+import static org.lwjgl.system.MemoryUtil.memAllocPointer;
+import static org.lwjgl.system.MemoryUtil.memFree;
+import static org.lwjgl.system.MemoryUtil.memUTF8;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_anyhit_shader;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_closesthit_shader;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_compilation_status_success;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_compile_into_spv;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_compile_options_initialize;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_compile_options_set_include_callbacks;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_compile_options_set_optimization_level;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_compiler_initialize;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_compiler_release;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_fragment_shader;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_miss_shader;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_optimization_level_performance;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_raygen_shader;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_result_get_bytes;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_result_get_compilation_status;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_result_get_error_message;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_result_get_length;
+import static org.lwjgl.util.shaderc.Shaderc.shaderc_vertex_shader;
+import static org.lwjgl.vulkan.EXTDebugReport.VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
+import static org.lwjgl.vulkan.EXTDebugReport.vkCreateDebugReportCallbackEXT;
+import static org.lwjgl.vulkan.KHRSurface.VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
+import static org.lwjgl.vulkan.KHRSurface.VK_ERROR_SURFACE_LOST_KHR;
 
 import java.io.IOException;
-import java.nio.*;
+import java.nio.ByteBuffer;
+import java.nio.LongBuffer;
 
-import org.lwjgl.*;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.PointerBuffer;
 import org.lwjgl.system.MemoryStack;
-import org.lwjgl.util.shaderc.*;
-import org.lwjgl.vulkan.*;
+import org.lwjgl.util.shaderc.ShadercIncludeResolve;
+import org.lwjgl.util.shaderc.ShadercIncludeResult;
+import org.lwjgl.util.shaderc.ShadercIncludeResultRelease;
+import org.lwjgl.vulkan.EXTDebugReport;
+import org.lwjgl.vulkan.KHRDisplaySwapchain;
+import org.lwjgl.vulkan.KHRSwapchain;
+import org.lwjgl.vulkan.NVRayTracing;
+import org.lwjgl.vulkan.VK10;
+import org.lwjgl.vulkan.VK12;
+import org.lwjgl.vulkan.VkClearValue;
+import org.lwjgl.vulkan.VkCommandBuffer;
+import org.lwjgl.vulkan.VkCommandBufferAllocateInfo;
+import org.lwjgl.vulkan.VkCommandBufferBeginInfo;
+import org.lwjgl.vulkan.VkDebugReportCallbackCreateInfoEXT;
+import org.lwjgl.vulkan.VkDebugReportCallbackEXT;
+import org.lwjgl.vulkan.VkDevice;
+import org.lwjgl.vulkan.VkInstance;
+import org.lwjgl.vulkan.VkRect2D;
+import org.lwjgl.vulkan.VkRenderPassBeginInfo;
+import org.lwjgl.vulkan.VkViewport;
 
 import com.github.hydos.ginger.engine.common.tools.IOUtil;
+import com.github.hydos.ginger.engine.vulkan.VKConstants;
+import com.github.hydos.ginger.engine.vulkan.shaders.Pipeline;
 
-/** @author hydos06
+/** @author hydos
  *         a util library for Vulkan */
 public class VKUtils
 {
@@ -164,12 +208,6 @@ public class VKUtils
 		}
 	}
 	
-	public static class Pipeline
-	{
-		public long pipeline;
-		public long layout;
-	}
-	
 	public static VkCommandBuffer[] initRenderCommandBuffers(VkDevice device, long commandPool, long[] framebuffers, long renderPass, int width, int height,
 		Pipeline pipeline, long descriptorSet, long verticesBuf)
 	{
diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VulkanFuncWrapper.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VulkanFuncWrapper.java
index b8dea9d..64f1163 100644
--- a/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VulkanFuncWrapper.java
+++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/utils/VulkanFuncWrapper.java
@@ -12,7 +12,12 @@ import static org.lwjgl.vulkan.VK10.*;
 import org.lwjgl.system.MemoryStack;
 import org.lwjgl.util.vma.*;
 import org.lwjgl.vulkan.*;
-
+/**
+ * 
+ * @author hydos
+ * used to make the vulkan api more readable
+ *
+ */
 public class VulkanFuncWrapper
 {
 	public static VmaVulkanFunctions VmaVulkanFunctions(MemoryStack stack)