getting closer to loading models

pull/12/head
hYdos 2020-03-03 20:34:37 +10:00
parent a1bddbaf5a
commit 49d3298bda
4 changed files with 381 additions and 111 deletions

View File

@ -14,6 +14,7 @@ import com.github.hydos.ginger.engine.common.obj.ModelLoader;
import com.github.hydos.ginger.engine.vulkan.*;
import com.github.hydos.ginger.engine.vulkan.api.VKGinger;
import com.github.hydos.ginger.engine.vulkan.model.*;
import com.github.hydos.ginger.engine.vulkan.registers.VKRegister;
import com.github.hydos.ginger.engine.vulkan.render.renderers.*;
import com.github.hydos.ginger.engine.vulkan.render.ubo.*;
import com.github.hydos.ginger.engine.vulkan.shaders.*;
@ -231,6 +232,7 @@ public class VulkanStarter
{
Window.create(1200, 600, "Litecraft Vulkan", 60, RenderAPI.Vulkan);
new VKGinger();
VKRegister.exampleVKModel = new VKModelData();
/* Look for instance extensions */
PointerBuffer requiredExtensions = GLFWVulkan.glfwGetRequiredInstanceExtensions();
if (requiredExtensions == null)
@ -239,9 +241,9 @@ public class VulkanStarter
final VkInstance vulkanInstance = VKLoader.createInstance(requiredExtensions);
VKUtils.setupVulkanDebugCallback();
final long debugCallbackHandle = VKUtils.startVulkanDebugging(vulkanInstance, EXTDebugReport.VK_DEBUG_REPORT_ERROR_BIT_EXT | EXTDebugReport.VK_DEBUG_REPORT_WARNING_BIT_EXT, VKConstants.debugCallback);
final VkPhysicalDevice physicalDevice = VKDeviceProperties.getFirstPhysicalDevice(vulkanInstance);
final VKDeviceProperties deviceAndGraphicsQueueFamily = VKDeviceProperties.initDeviceProperties(physicalDevice);
final VkDevice device = deviceAndGraphicsQueueFamily.device;
VKRegister.physicalDevice = VKDeviceProperties.getFirstPhysicalDevice(vulkanInstance);
final VKDeviceProperties deviceAndGraphicsQueueFamily = VKDeviceProperties.initDeviceProperties(VKRegister.physicalDevice);
VKRegister.device = deviceAndGraphicsQueueFamily.device;
int queueFamilyIndex = deviceAndGraphicsQueueFamily.queueFamilyIndex;
final VkPhysicalDeviceMemoryProperties memoryProperties = deviceAndGraphicsQueueFamily.memoryProperties;
GLFWKeyCallback keyCallback;
@ -261,18 +263,19 @@ public class VulkanStarter
if (err != VK12.VK_SUCCESS)
{ throw new AssertionError("Failed to create surface: " + VKUtils.translateVulkanResult(err)); }
// Create static Vulkan resources
final ColorAndDepthFormatAndSpace colorAndDepthFormatAndSpace = VKMasterRenderer.getColorFormatAndSpace(physicalDevice, surface);
final long commandPool = createCommandPool(device, queueFamilyIndex);
final VkCommandBuffer setupCommandBuffer = createCommandBuffer(device, commandPool);
final VkQueue queue = createDeviceQueue(device, queueFamilyIndex);
final long renderPass = ExampleRenderer.createRenderPass(device, colorAndDepthFormatAndSpace.colorFormat, colorAndDepthFormatAndSpace.depthFormat);
final long renderCommandPool = createCommandPool(device, queueFamilyIndex);
VKVertices vertices = VKModelConverter.convertModel(ModelLoader.getCubeMesh(), memoryProperties, device);
Ubo ubo = new Ubo(memoryProperties, device);
final long descriptorPool = createDescriptorPool(device);
final long descriptorSetLayout = createDescriptorSetLayout(device);
final long descriptorSet = createDescriptorSet(device, descriptorPool, descriptorSetLayout, ubo.uboData);
final Pipeline pipeline = Pipeline.createPipeline(device, renderPass, vertices.createInfo, descriptorSetLayout);
final ColorAndDepthFormatAndSpace colorAndDepthFormatAndSpace = VKMasterRenderer.getColorFormatAndSpace(VKRegister.physicalDevice, surface);
VKRegister.commandPool = createCommandPool(VKRegister.device, queueFamilyIndex);
final VkCommandBuffer setupCommandBuffer = createCommandBuffer(VKRegister.device, VKRegister.commandPool);
VKRegister.queue = createDeviceQueue(VKRegister.device, queueFamilyIndex);
final long renderPass = ExampleRenderer.createRenderPass(VKRegister.device, colorAndDepthFormatAndSpace.colorFormat, colorAndDepthFormatAndSpace.depthFormat);
final long renderCommandPool = createCommandPool(VKRegister.device, queueFamilyIndex);
VKVertices vertices = VKModelConverter.convertModel(ModelLoader.getCubeMesh(), memoryProperties, VKRegister.device);
Ubo ubo = new Ubo(memoryProperties, VKRegister.device);
final long descriptorPool = createDescriptorPool(VKRegister.device);
final long descriptorSetLayout = createDescriptorSetLayout(VKRegister.device);
final long descriptorSet = createDescriptorSet(VKRegister.device, descriptorPool, descriptorSetLayout, ubo.uboData);
final Pipeline pipeline = Pipeline.createPipeline(VKRegister.device, renderPass, vertices.createInfo, descriptorSetLayout);
VKRegister.exampleVKModel.loadModel();
final class SwapchainRecreator
{
boolean mustRecreate = true;
@ -288,23 +291,23 @@ public class VulkanStarter
{ throw new AssertionError("Failed to begin setup command buffer: " + VKUtils.translateVulkanResult(err)); }
long oldChain = swapchain != null ? swapchain.swapchainHandle : VK12.VK_NULL_HANDLE;
// Create the swapchain (this will also add a memory barrier to initialize the framebuffer images)
swapchain = VKMasterRenderer.createSwapChain(device, physicalDevice, surface, oldChain, setupCommandBuffer,
swapchain = VKMasterRenderer.createSwapChain(VKRegister.device, VKRegister.physicalDevice, surface, oldChain, setupCommandBuffer,
Window.getWidth(), Window.getHeight(), colorAndDepthFormatAndSpace.colorFormat, colorAndDepthFormatAndSpace.colorSpace);
// Create depth-stencil image
depthStencil = VKMasterRenderer.createDepthStencil(device, memoryProperties, colorAndDepthFormatAndSpace.depthFormat, setupCommandBuffer);
depthStencil = VKMasterRenderer.createDepthStencil(VKRegister.device, memoryProperties, colorAndDepthFormatAndSpace.depthFormat, setupCommandBuffer);
err = VK12.vkEndCommandBuffer(setupCommandBuffer);
if (err != VK12.VK_SUCCESS)
{ throw new AssertionError("Failed to end setup command buffer: " + VKUtils.translateVulkanResult(err)); }
submitCommandBuffer(queue, setupCommandBuffer);
VK12.vkQueueWaitIdle(queue);
submitCommandBuffer(VKRegister.queue, setupCommandBuffer);
VK12.vkQueueWaitIdle(VKRegister.queue);
if (framebuffers != null)
{ for (int i = 0; i < framebuffers.length; i++)
VK12.vkDestroyFramebuffer(device, framebuffers[i], null); }
framebuffers = ExampleRenderer.createFramebuffers(device, swapchain, renderPass, Window.getWidth(), Window.getHeight(), depthStencil);
VK12.vkDestroyFramebuffer(VKRegister.device, framebuffers[i], null); }
framebuffers = ExampleRenderer.createFramebuffers(VKRegister.device, swapchain, renderPass, Window.getWidth(), Window.getHeight(), depthStencil);
// Create render command buffers
if (renderCommandBuffers != null)
{ VK12.vkResetCommandPool(device, renderCommandPool, VKUtils.VK_FLAGS_NONE); }
renderCommandBuffers = VKUtils.initRenderCommandBuffers(device, renderCommandPool, framebuffers, renderPass, Window.getWidth(), Window.getHeight(), pipeline, descriptorSet,
{ VK12.vkResetCommandPool(VKRegister.device, renderCommandPool, VKUtils.VK_FLAGS_NONE); }
renderCommandBuffers = VKUtils.initRenderCommandBuffers(VKRegister.device, renderCommandPool, framebuffers, renderPass, Window.getWidth(), Window.getHeight(), pipeline, descriptorSet,
vertices.vkVerticiesBuffer);
mustRecreate = false;
}
@ -360,16 +363,16 @@ public class VulkanStarter
swapchainRecreator.recreate();
err = VK12.vkCreateSemaphore(device, semaphoreCreateInfo, null, pImageAcquiredSemaphore);
err = VK12.vkCreateSemaphore(VKRegister.device, semaphoreCreateInfo, null, pImageAcquiredSemaphore);
if (err != VK12.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 = VK12.vkCreateSemaphore(device, semaphoreCreateInfo, null, pRenderCompleteSemaphore);
err = VK12.vkCreateSemaphore(VKRegister.device, semaphoreCreateInfo, null, pRenderCompleteSemaphore);
if (err != VK12.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 = KHRSwapchain.vkAcquireNextImageKHR(device, swapchain.swapchainHandle, VKConstants.MAX_UNSIGNED_INT, pImageAcquiredSemaphore.get(0), VK12.VK_NULL_HANDLE, pImageIndex);
err = KHRSwapchain.vkAcquireNextImageKHR(VKRegister.device, swapchain.swapchainHandle, VKConstants.MAX_UNSIGNED_INT, pImageAcquiredSemaphore.get(0), VK12.VK_NULL_HANDLE, pImageIndex);
currentBuffer = pImageIndex.get(0);
if (err != VK12.VK_SUCCESS)
{ throw new AssertionError("Failed to acquire next swapchain image: " + VKUtils.translateVulkanResult(err)); }
@ -379,23 +382,23 @@ public class VulkanStarter
long thisTime = System.nanoTime();
time += (thisTime - lastTime) / 1E9f;
lastTime = thisTime;
ubo.updateUbo(device, time);
ubo.updateUbo(VKRegister.device, time);
// Submit to the graphics queue
err = VK12.vkQueueSubmit(queue, submitInfo, VK12.VK_NULL_HANDLE);
err = VK12.vkQueueSubmit(VKRegister.queue, submitInfo, VK12.VK_NULL_HANDLE);
if (err != VK12.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 = KHRSwapchain.vkQueuePresentKHR(queue, presentInfo);
err = KHRSwapchain.vkQueuePresentKHR(VKRegister.queue, presentInfo);
if (err != VK12.VK_SUCCESS)
{ throw new AssertionError("Failed to present the swapchain image: " + VKUtils.translateVulkanResult(err)); }
// Create and submit post present barrier
VK12.vkQueueWaitIdle(queue);
VK12.vkQueueWaitIdle(VKRegister.queue);
// Destroy this semaphore (we will create a new one in the next frame)
VK12.vkDestroySemaphore(device, pImageAcquiredSemaphore.get(0), null);
VK12.vkDestroySemaphore(device, pRenderCompleteSemaphore.get(0), null);
VK12.vkDestroySemaphore(VKRegister.device, pImageAcquiredSemaphore.get(0), null);
VK12.vkDestroySemaphore(VKRegister.device, pRenderCompleteSemaphore.get(0), null);
}
VKGinger.getInstance().end(pWaitDstStageMask, pImageAcquiredSemaphore, pRenderCompleteSemaphore, pSwapchains, pCommandBuffers, semaphoreCreateInfo, submitInfo, presentInfo, vulkanInstance, debugCallbackHandle, framebufferSizeCallback, keyCallback);
}

View File

@ -0,0 +1,240 @@
package com.github.hydos.ginger.engine.vulkan.model;
import static org.lwjgl.system.MemoryStack.stackPush;
import java.nio.*;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.*;
import com.github.hydos.ginger.engine.common.obj.*;
import com.github.hydos.ginger.engine.vulkan.registers.VKRegister;
public class VKModelData
{
public Mesh mesh;
public long vertexBuffer;
public long vertexBufferMemory;
public long indexBuffer;
public long indexBufferMemory;
public void loadModel() {
this.mesh = ModelLoader.getCubeMesh();
createIndexBuffer();
createVertexBuffer();
}
public int findMemoryType(int typeFilter, int properties) {
VkPhysicalDeviceMemoryProperties memProperties = VkPhysicalDeviceMemoryProperties.mallocStack();
VK12.vkGetPhysicalDeviceMemoryProperties(VKRegister.physicalDevice, memProperties);
for(int i = 0;i < memProperties.memoryTypeCount();i++) {
if((typeFilter & (1 << i)) != 0 && (memProperties.memoryTypes(i).propertyFlags() & properties) == properties) {
return i;
}
}
throw new RuntimeException("Failed to find suitable memory type");
}
public void createBuffer(long size, int usage, int properties, LongBuffer pBuffer, LongBuffer pBufferMemory) {
try(MemoryStack stack = stackPush()) {
VkBufferCreateInfo bufferInfo = VkBufferCreateInfo.callocStack(stack);
bufferInfo.sType(VK12.VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
bufferInfo.size(size);
bufferInfo.usage(usage);
bufferInfo.sharingMode(VK12.VK_SHARING_MODE_EXCLUSIVE);
if(VK12.vkCreateBuffer(VKRegister.device, bufferInfo, null, pBuffer) != VK12.VK_SUCCESS) {
throw new RuntimeException("Failed to create vertex buffer");
}
VkMemoryRequirements memRequirements = VkMemoryRequirements.mallocStack(stack);
VK12.vkGetBufferMemoryRequirements(VKRegister.device, pBuffer.get(0), memRequirements);
VkMemoryAllocateInfo allocInfo = VkMemoryAllocateInfo.callocStack(stack);
allocInfo.sType(VK12.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
allocInfo.allocationSize(memRequirements.size());
allocInfo.memoryTypeIndex(findMemoryType(memRequirements.memoryTypeBits(), properties));
if(VK12.vkAllocateMemory(VKRegister.device, allocInfo, null, pBufferMemory) != VK12.VK_SUCCESS) {
throw new RuntimeException("Failed to allocate vertex buffer memory");
}
VK12.vkBindBufferMemory(VKRegister.device, pBuffer.get(0), pBufferMemory.get(0), 0);
}
}
private void endSingleTimeCommands(VkCommandBuffer commandBuffer) {
try(MemoryStack stack = stackPush()) {
VK12.vkEndCommandBuffer(commandBuffer);
VkSubmitInfo.Buffer submitInfo = VkSubmitInfo.callocStack(1, stack);
submitInfo.sType(VK12.VK_STRUCTURE_TYPE_SUBMIT_INFO);
submitInfo.pCommandBuffers(stack.pointers(commandBuffer));
VK12.vkQueueSubmit(VKRegister.queue, submitInfo, VK12.VK_NULL_HANDLE);
VK12.vkQueueWaitIdle(VKRegister.queue);
VK12.vkFreeCommandBuffers(VKRegister.device, VKRegister.commandPool, commandBuffer);
}
}
private VkCommandBuffer beginSingleTimeCommands() {
try(MemoryStack stack = stackPush()) {
VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo.callocStack(stack);
allocInfo.sType(VK12.VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO);
allocInfo.level(VK12.VK_COMMAND_BUFFER_LEVEL_PRIMARY);
allocInfo.commandPool(VKRegister.commandPool);
allocInfo.commandBufferCount(1);
PointerBuffer pCommandBuffer = stack.mallocPointer(1);
VK12.vkAllocateCommandBuffers(VKRegister.device, allocInfo, pCommandBuffer);
VkCommandBuffer commandBuffer = new VkCommandBuffer(pCommandBuffer.get(0), VKRegister.device);
VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo.callocStack(stack);
beginInfo.sType(VK12.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO);
beginInfo.flags(VK12.VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
VK12.vkBeginCommandBuffer(commandBuffer, beginInfo);
return commandBuffer;
}
}
private void copyBuffer(long srcBuffer, long dstBuffer, long size) {
try(MemoryStack stack = stackPush()) {
VkCommandBuffer commandBuffer = beginSingleTimeCommands();
VkBufferCopy.Buffer copyRegion = VkBufferCopy.callocStack(1, stack);
copyRegion.size(size);
VK12.vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, copyRegion);
endSingleTimeCommands(commandBuffer);
}
}
private void memcpy(ByteBuffer buffer, int[] vertices) {
int i = 1;
for(int vertex : vertices) {
buffer.putFloat(vertex);
if(i == 3) {
buffer.putFloat(1);
buffer.putFloat(1);
buffer.putFloat(1);
buffer.putFloat(1);
buffer.putFloat(1);
i = 0;
}
//TODO: Finish
i++;
}
}
private void memcpy(ByteBuffer buffer, float[] indices) {
for(float index : indices) {
buffer.putFloat(index);
}
buffer.rewind();
}
private void createVertexBuffer() {
try(MemoryStack stack = stackPush()) {
long bufferSize = 3 * mesh.getVertices().length;
LongBuffer pBuffer = stack.mallocLong(1);
LongBuffer pBufferMemory = stack.mallocLong(1);
createBuffer(bufferSize,
VK12.VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK12.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK12.VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
pBuffer,
pBufferMemory);
long stagingBuffer = pBuffer.get(0);
long stagingBufferMemory = pBufferMemory.get(0);
PointerBuffer data = stack.mallocPointer(1);
VK12.vkMapMemory(VKRegister.device, stagingBufferMemory, 0, bufferSize, 0, data);
{
memcpy(data.getByteBuffer(0, (int) bufferSize), mesh.getVertices());
}
VK12.vkUnmapMemory(VKRegister.device, stagingBufferMemory);
createBuffer(bufferSize,
VK12.VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK12.VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK12.VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
pBuffer,
pBufferMemory);
vertexBuffer = pBuffer.get(0);
vertexBufferMemory = pBufferMemory.get(0);
copyBuffer(stagingBuffer, vertexBuffer, bufferSize);
VK12.vkDestroyBuffer(VKRegister.device, stagingBuffer, null);
VK12.vkFreeMemory(VKRegister.device, stagingBufferMemory, null);
}
}
private void createIndexBuffer() {
try(MemoryStack stack = stackPush()) {
long bufferSize = Integer.BYTES * mesh.getIndices().length;
LongBuffer pBuffer = stack.mallocLong(1);
LongBuffer pBufferMemory = stack.mallocLong(1);
createBuffer(bufferSize,
VK12.VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK12.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK12.VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
pBuffer,
pBufferMemory);
long stagingBuffer = pBuffer.get(0);
long stagingBufferMemory = pBufferMemory.get(0);
PointerBuffer data = stack.mallocPointer(1);
VK12.vkMapMemory(VKRegister.device, stagingBufferMemory, 0, bufferSize, 0, data);
{
memcpy(data.getByteBuffer(0, (int) bufferSize), mesh.getIndices());
}
VK12.vkUnmapMemory(VKRegister.device, stagingBufferMemory);
createBuffer(bufferSize,
VK12.VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK12.VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VK12.VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
pBuffer,
pBufferMemory);
indexBuffer = pBuffer.get(0);
indexBufferMemory = pBufferMemory.get(0);
copyBuffer(stagingBuffer, indexBuffer, bufferSize);
VK12.vkDestroyBuffer(VKRegister.device, stagingBuffer, null);
VK12.vkFreeMemory(VKRegister.device, stagingBufferMemory, null);
}
}
}

View File

@ -0,0 +1,18 @@
package com.github.hydos.ginger.engine.vulkan.registers;
import org.lwjgl.vulkan.*;
import com.github.hydos.ginger.engine.vulkan.model.VKModelData;
public class VKRegister
{
public static VkDevice device;
public static VkQueue queue;
public static long commandPool;
public static VkPhysicalDevice physicalDevice;
public static VKModelData exampleVKModel;
}

View File

@ -15,6 +15,7 @@ import org.lwjgl.vulkan.*;
import com.github.hydos.ginger.engine.common.tools.IOUtil;
import com.github.hydos.ginger.engine.vulkan.VKConstants;
import com.github.hydos.ginger.engine.vulkan.registers.VKRegister;
import com.github.hydos.ginger.engine.vulkan.shaders.Pipeline;
/** @author hydos
@ -168,6 +169,8 @@ public class VKUtils
public static VkCommandBuffer[] initRenderCommandBuffers(VkDevice device, long commandPool, long[] framebuffers, long renderPass, int width, int height,
Pipeline pipeline, long descriptorSet, long verticesBuf)
{
try (MemoryStack stack = MemoryStack.stackPush())
{
// Create the render command buffers (one command buffer per framebuffer image)
VkCommandBufferAllocateInfo cmdBufAllocateInfo = VkCommandBufferAllocateInfo.calloc()
@ -237,11 +240,14 @@ public class VKUtils
offsets.put(0, 0L);
LongBuffer pBuffers = memAllocLong(1);
pBuffers.put(0, verticesBuf);
VK12.vkCmdBindVertexBuffers(renderCommandBuffers[i], 0, pBuffers, offsets);
LongBuffer vertexBuffers = stack.longs(VKRegister.exampleVKModel.vertexBuffer);
VK12.vkCmdBindVertexBuffers(renderCommandBuffers[i], 0, vertexBuffers, offsets);
VK12.vkCmdBindIndexBuffer(renderCommandBuffers[i], VKRegister.exampleVKModel.indexBuffer, 0, 3);// 3 = VK_INDEX_TYPE_UINT32
memFree(pBuffers);
memFree(offsets);
// Draw triangle
VK12.vkCmdDraw(renderCommandBuffers[i], 6, 1, 0, 0);
// Draw model
// VK12.vkCmdDraw(renderCommandBuffers[i], 6, 1, 0, 0); old method
VK12.vkCmdDrawIndexed(renderCommandBuffers[i], VKRegister.exampleVKModel.mesh.getIndices().length, 1, 0, 0, 0);
VK12.vkCmdEndRenderPass(renderCommandBuffers[i]);
err = VK12.vkEndCommandBuffer(renderCommandBuffers[i]);
if (err != VK12.VK_SUCCESS)
@ -253,6 +259,9 @@ public class VKUtils
return renderCommandBuffers;
}
}
public static void setupVulkanDebugCallback()
{
VKConstants.debugCallback = new VkDebugReportCallbackEXT()