From 49d3298bda62c4fba84c51d703febf41fe3ba074 Mon Sep 17 00:00:00 2001 From: hYdos Date: Tue, 3 Mar 2020 20:34:37 +1000 Subject: [PATCH] getting closer to loading models --- .../github/hydos/ginger/VulkanStarter.java | 67 ++--- .../engine/vulkan/model/VKModelData.java | 240 ++++++++++++++++++ .../engine/vulkan/registers/VKRegister.java | 18 ++ .../ginger/engine/vulkan/utils/VKUtils.java | 167 ++++++------ 4 files changed, 381 insertions(+), 111 deletions(-) create mode 100644 src/main/java/com/github/hydos/ginger/engine/vulkan/model/VKModelData.java create mode 100644 src/main/java/com/github/hydos/ginger/engine/vulkan/registers/VKRegister.java diff --git a/src/main/java/com/github/hydos/ginger/VulkanStarter.java b/src/main/java/com/github/hydos/ginger/VulkanStarter.java index c464550..3c034be 100644 --- a/src/main/java/com/github/hydos/ginger/VulkanStarter.java +++ b/src/main/java/com/github/hydos/ginger/VulkanStarter.java @@ -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); } diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/model/VKModelData.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/model/VKModelData.java new file mode 100644 index 0000000..64e283f --- /dev/null +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/model/VKModelData.java @@ -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); + } + } + +} diff --git a/src/main/java/com/github/hydos/ginger/engine/vulkan/registers/VKRegister.java b/src/main/java/com/github/hydos/ginger/engine/vulkan/registers/VKRegister.java new file mode 100644 index 0000000..43d3d92 --- /dev/null +++ b/src/main/java/com/github/hydos/ginger/engine/vulkan/registers/VKRegister.java @@ -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; + + + +} 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 1582261..a36d735 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 @@ -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 @@ -169,88 +170,96 @@ 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) { - // Create the render command buffers (one command buffer per framebuffer image) - VkCommandBufferAllocateInfo cmdBufAllocateInfo = VkCommandBufferAllocateInfo.calloc() - .sType(VK12.VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO) - .commandPool(commandPool) - .level(VK12.VK_COMMAND_BUFFER_LEVEL_PRIMARY) - .commandBufferCount(framebuffers.length); - PointerBuffer pCommandBuffer = memAllocPointer(framebuffers.length); - int err = VK12.vkAllocateCommandBuffers(device, cmdBufAllocateInfo, pCommandBuffer); - if (err != VK12.VK_SUCCESS) - { throw new AssertionError("Failed to create 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(VK12.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(VK12.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) + try (MemoryStack stack = MemoryStack.stackPush()) { - // Set target frame buffer - renderPassBeginInfo.framebuffer(framebuffers[i]); - err = VK12.vkBeginCommandBuffer(renderCommandBuffers[i], cmdBufInfo); + // Create the render command buffers (one command buffer per framebuffer image) + VkCommandBufferAllocateInfo cmdBufAllocateInfo = VkCommandBufferAllocateInfo.calloc() + .sType(VK12.VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO) + .commandPool(commandPool) + .level(VK12.VK_COMMAND_BUFFER_LEVEL_PRIMARY) + .commandBufferCount(framebuffers.length); + PointerBuffer pCommandBuffer = memAllocPointer(framebuffers.length); + int err = VK12.vkAllocateCommandBuffers(device, cmdBufAllocateInfo, pCommandBuffer); if (err != VK12.VK_SUCCESS) - { throw new AssertionError("Failed to begin render command buffer: " + VKUtils.translateVulkanResult(err)); } - VK12.vkCmdBeginRenderPass(renderCommandBuffers[i], renderPassBeginInfo, VK12.VK_SUBPASS_CONTENTS_INLINE); - // Update dynamic viewport state - VkViewport.Buffer viewport = VkViewport.calloc(1) - .height(height) - .width(width) - .minDepth(0.0f) - .maxDepth(1.0f); - VK12.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); - VK12.vkCmdSetScissor(renderCommandBuffers[i], 0, scissor); - scissor.free(); - // Bind descriptor sets describing shader binding points - LongBuffer descriptorSets = memAllocLong(1).put(0, descriptorSet); - VK12.vkCmdBindDescriptorSets(renderCommandBuffers[i], VK12.VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, descriptorSets, null); - memFree(descriptorSets); - // Bind the rendering pipeline (including the shaders) - VK12.vkCmdBindPipeline(renderCommandBuffers[i], VK12.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); - VK12.vkCmdBindVertexBuffers(renderCommandBuffers[i], 0, pBuffers, offsets); - memFree(pBuffers); - memFree(offsets); - // Draw triangle - VK12.vkCmdDraw(renderCommandBuffers[i], 6, 1, 0, 0); - VK12.vkCmdEndRenderPass(renderCommandBuffers[i]); - err = VK12.vkEndCommandBuffer(renderCommandBuffers[i]); - if (err != VK12.VK_SUCCESS) - { throw new AssertionError("Failed to begin render command buffer: " + VKUtils.translateVulkanResult(err)); } + { throw new AssertionError("Failed to create 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(VK12.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(VK12.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 = VK12.vkBeginCommandBuffer(renderCommandBuffers[i], cmdBufInfo); + if (err != VK12.VK_SUCCESS) + { throw new AssertionError("Failed to begin render command buffer: " + VKUtils.translateVulkanResult(err)); } + VK12.vkCmdBeginRenderPass(renderCommandBuffers[i], renderPassBeginInfo, VK12.VK_SUBPASS_CONTENTS_INLINE); + // Update dynamic viewport state + VkViewport.Buffer viewport = VkViewport.calloc(1) + .height(height) + .width(width) + .minDepth(0.0f) + .maxDepth(1.0f); + VK12.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); + VK12.vkCmdSetScissor(renderCommandBuffers[i], 0, scissor); + scissor.free(); + // Bind descriptor sets describing shader binding points + LongBuffer descriptorSets = memAllocLong(1).put(0, descriptorSet); + VK12.vkCmdBindDescriptorSets(renderCommandBuffers[i], VK12.VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, descriptorSets, null); + memFree(descriptorSets); + // Bind the rendering pipeline (including the shaders) + VK12.vkCmdBindPipeline(renderCommandBuffers[i], VK12.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); + 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 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) + { throw new AssertionError("Failed to begin render command buffer: " + VKUtils.translateVulkanResult(err)); } + } + renderPassBeginInfo.free(); + clearValues.free(); + cmdBufInfo.free(); + return renderCommandBuffers; } - renderPassBeginInfo.free(); - clearValues.free(); - cmdBufInfo.free(); - return renderCommandBuffers; + + } public static void setupVulkanDebugCallback()