406 lines
19 KiB
Java
406 lines
19 KiB
Java
package com.github.hydos.ginger;
|
|
|
|
import java.io.IOException;
|
|
import java.nio.*;
|
|
|
|
import org.lwjgl.PointerBuffer;
|
|
import org.lwjgl.glfw.*;
|
|
import org.lwjgl.system.MemoryUtil;
|
|
import org.lwjgl.vulkan.*;
|
|
|
|
import com.github.hydos.ginger.engine.common.info.RenderAPI;
|
|
import com.github.hydos.ginger.engine.common.io.Window;
|
|
import com.github.hydos.ginger.engine.common.obj.ModelLoader;
|
|
import com.github.hydos.ginger.engine.vulkan.*;
|
|
import com.github.hydos.ginger.engine.vulkan.api.GingerVK;
|
|
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.RenderUtils;
|
|
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.*;
|
|
import com.github.hydos.ginger.engine.vulkan.utils.*;
|
|
|
|
/** @author hydos06
|
|
* the non ARR vulkan test example */
|
|
public class VulkanStarter
|
|
{
|
|
public static boolean getSupportedDepthFormat(VkPhysicalDevice physicalDevice, IntBuffer depthFormat)
|
|
{
|
|
// Since all depth formats may be optional, we need to find a suitable depth format to use
|
|
// Start with the highest precision packed format
|
|
int[] depthFormats =
|
|
{
|
|
VK12.VK_FORMAT_D32_SFLOAT_S8_UINT,
|
|
VK12.VK_FORMAT_D32_SFLOAT,
|
|
VK12.VK_FORMAT_D24_UNORM_S8_UINT,
|
|
VK12.VK_FORMAT_D16_UNORM_S8_UINT,
|
|
VK12.VK_FORMAT_D16_UNORM
|
|
};
|
|
VkFormatProperties formatProps = VkFormatProperties.calloc();
|
|
for (int format : depthFormats)
|
|
{
|
|
VK12.vkGetPhysicalDeviceFormatProperties(physicalDevice, format, formatProps);
|
|
// Format must support depth stencil attachment for optimal tiling
|
|
if ((formatProps.optimalTilingFeatures() & VK12.VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0)
|
|
{
|
|
depthFormat.put(0, format);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static class ColorAndDepthFormatAndSpace
|
|
{
|
|
public int colorFormat;
|
|
public int colorSpace;
|
|
public int depthFormat;
|
|
}
|
|
|
|
private static long createCommandPool(VkDevice device, int queueNodeIndex)
|
|
{
|
|
VkCommandPoolCreateInfo cmdPoolInfo = VkCommandPoolCreateInfo.calloc()
|
|
.sType(VK12.VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO)
|
|
.queueFamilyIndex(queueNodeIndex)
|
|
.flags(VK12.VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
|
LongBuffer pCmdPool = MemoryUtil.memAllocLong(1);
|
|
int err = VK12.vkCreateCommandPool(device, cmdPoolInfo, null, pCmdPool);
|
|
long commandPool = pCmdPool.get(0);
|
|
cmdPoolInfo.free();
|
|
MemoryUtil.memFree(pCmdPool);
|
|
if (err != VK12.VK_SUCCESS)
|
|
{ throw new AssertionError("Failed to create command pool: " + VKUtils.translateVulkanResult(err)); }
|
|
return commandPool;
|
|
}
|
|
|
|
private static VkQueue createDeviceQueue(VkDevice device, int queueFamilyIndex)
|
|
{
|
|
PointerBuffer pQueue = MemoryUtil.memAllocPointer(1);
|
|
VK12.vkGetDeviceQueue(device, queueFamilyIndex, 0, pQueue);
|
|
long queue = pQueue.get(0);
|
|
MemoryUtil.memFree(pQueue);
|
|
return new VkQueue(queue, device);
|
|
}
|
|
|
|
private static VkCommandBuffer createCommandBuffer(VkDevice device, long commandPool)
|
|
{
|
|
VkCommandBufferAllocateInfo cmdBufAllocateInfo = VkCommandBufferAllocateInfo.calloc()
|
|
.sType(VK12.VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO)
|
|
.commandPool(commandPool)
|
|
.level(VK12.VK_COMMAND_BUFFER_LEVEL_PRIMARY)
|
|
.commandBufferCount(1);
|
|
PointerBuffer pCommandBuffer = MemoryUtil.memAllocPointer(1);
|
|
int err = VK12.vkAllocateCommandBuffers(device, cmdBufAllocateInfo, pCommandBuffer);
|
|
cmdBufAllocateInfo.free();
|
|
long commandBuffer = pCommandBuffer.get(0);
|
|
MemoryUtil.memFree(pCommandBuffer);
|
|
if (err != VK12.VK_SUCCESS)
|
|
{ throw new AssertionError("Failed to allocate command buffer: " + VKUtils.translateVulkanResult(err)); }
|
|
return new VkCommandBuffer(commandBuffer, device);
|
|
}
|
|
|
|
public static class Swapchain
|
|
{
|
|
public long swapchainHandle;
|
|
public long[] images;
|
|
public long[] imageViews;
|
|
}
|
|
|
|
public static class DepthStencil
|
|
{
|
|
public long view;
|
|
}
|
|
|
|
private static void submitCommandBuffer(VkQueue queue, VkCommandBuffer commandBuffer)
|
|
{
|
|
if (commandBuffer == null || commandBuffer.address() == MemoryUtil.NULL)
|
|
return;
|
|
VkSubmitInfo submitInfo = VkSubmitInfo.calloc()
|
|
.sType(VK12.VK_STRUCTURE_TYPE_SUBMIT_INFO);
|
|
PointerBuffer pCommandBuffers = MemoryUtil.memAllocPointer(1)
|
|
.put(commandBuffer)
|
|
.flip();
|
|
submitInfo.pCommandBuffers(pCommandBuffers);
|
|
int err = VK12.vkQueueSubmit(queue, submitInfo, VK12.VK_NULL_HANDLE);
|
|
MemoryUtil.memFree(pCommandBuffers);
|
|
submitInfo.free();
|
|
if (err != VK12.VK_SUCCESS)
|
|
{ throw new AssertionError("Failed to submit command buffer: " + VKUtils.translateVulkanResult(err)); }
|
|
}
|
|
|
|
private static long createDescriptorPool(VkDevice device)
|
|
{
|
|
// We need to tell the API the number of max. requested descriptors per type
|
|
VkDescriptorPoolSize.Buffer typeCounts = VkDescriptorPoolSize.calloc(1)
|
|
// This example only uses one descriptor type (uniform buffer) and only
|
|
// requests one descriptor of this type
|
|
.type(VK12.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
|
|
.descriptorCount(1);
|
|
// For additional types you need to add new entries in the type count list
|
|
// E.g. for two combined image samplers :
|
|
// typeCounts[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
// typeCounts[1].descriptorCount = 2;
|
|
// Create the global descriptor pool
|
|
// All descriptors used in this example are allocated from this pool
|
|
VkDescriptorPoolCreateInfo descriptorPoolInfo = VkDescriptorPoolCreateInfo.calloc()
|
|
.sType(VK12.VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO)
|
|
.pPoolSizes(typeCounts)
|
|
// Set the max. number of sets that can be requested
|
|
// Requesting descriptors beyond maxSets will result in an error
|
|
.maxSets(1);
|
|
LongBuffer pDescriptorPool = MemoryUtil.memAllocLong(1);
|
|
int err = VK12.vkCreateDescriptorPool(device, descriptorPoolInfo, null, pDescriptorPool);
|
|
long descriptorPool = pDescriptorPool.get(0);
|
|
MemoryUtil.memFree(pDescriptorPool);
|
|
descriptorPoolInfo.free();
|
|
typeCounts.free();
|
|
if (err != VK12.VK_SUCCESS)
|
|
{ throw new AssertionError("Failed to create descriptor pool: " + VKUtils.translateVulkanResult(err)); }
|
|
return descriptorPool;
|
|
}
|
|
|
|
private static long createDescriptorSet(VkDevice device, long descriptorPool, long descriptorSetLayout, UboDescriptor uniformDataVSDescriptor)
|
|
{
|
|
LongBuffer pDescriptorSetLayout = MemoryUtil.memAllocLong(1);
|
|
pDescriptorSetLayout.put(0, descriptorSetLayout);
|
|
VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo.calloc()
|
|
.sType(VK12.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO)
|
|
.descriptorPool(descriptorPool)
|
|
.pSetLayouts(pDescriptorSetLayout);
|
|
LongBuffer pDescriptorSet = MemoryUtil.memAllocLong(1);
|
|
int err = VK12.vkAllocateDescriptorSets(device, allocInfo, pDescriptorSet);
|
|
long descriptorSet = pDescriptorSet.get(0);
|
|
MemoryUtil.memFree(pDescriptorSet);
|
|
allocInfo.free();
|
|
MemoryUtil.memFree(pDescriptorSetLayout);
|
|
if (err != VK12.VK_SUCCESS)
|
|
{ throw new AssertionError("Failed to create descriptor set: " + VKUtils.translateVulkanResult(err)); }
|
|
// Update descriptor sets determining the shader binding points
|
|
// For every binding point used in a shader there needs to be one
|
|
// descriptor set matching that binding point
|
|
VkDescriptorBufferInfo.Buffer descriptor = VkDescriptorBufferInfo.calloc(1)
|
|
.buffer(uniformDataVSDescriptor.buffer)
|
|
.range(uniformDataVSDescriptor.range)
|
|
.offset(uniformDataVSDescriptor.offset);
|
|
// Binding 0 : Uniform buffer
|
|
VkWriteDescriptorSet.Buffer writeDescriptorSet = VkWriteDescriptorSet.calloc(1)
|
|
.sType(VK12.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET)
|
|
.dstSet(descriptorSet)
|
|
.descriptorCount(1)
|
|
.descriptorType(VK12.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
|
|
.pBufferInfo(descriptor)
|
|
.dstBinding(0); // Binds this uniform buffer to binding point 0
|
|
VK12.vkUpdateDescriptorSets(device, writeDescriptorSet, null);
|
|
writeDescriptorSet.free();
|
|
descriptor.free();
|
|
return descriptorSet;
|
|
}
|
|
|
|
private static long createDescriptorSetLayout(VkDevice device)
|
|
{
|
|
int err;
|
|
// One binding for a UBO used in a vertex shader
|
|
VkDescriptorSetLayoutBinding.Buffer layoutBinding = VkDescriptorSetLayoutBinding.calloc(1)
|
|
.binding(ShaderType.vertexShader) // <- Binding 0 : Uniform buffer (Vertex shader)
|
|
.descriptorType(VK12.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
|
|
.descriptorCount(1)
|
|
.stageFlags(VK12.VK_SHADER_STAGE_VERTEX_BIT);
|
|
// Build a create-info struct to create the descriptor set layout
|
|
VkDescriptorSetLayoutCreateInfo descriptorLayout = VkDescriptorSetLayoutCreateInfo.calloc()
|
|
.sType(VK12.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)
|
|
.pBindings(layoutBinding);
|
|
LongBuffer pDescriptorSetLayout = MemoryUtil.memAllocLong(1);
|
|
err = VK12.vkCreateDescriptorSetLayout(device, descriptorLayout, null, pDescriptorSetLayout);
|
|
long descriptorSetLayout = pDescriptorSetLayout.get(0);
|
|
MemoryUtil.memFree(pDescriptorSetLayout);
|
|
descriptorLayout.free();
|
|
layoutBinding.free();
|
|
if (err != VK12.VK_SUCCESS)
|
|
{ throw new AssertionError("Failed to create descriptor set layout: " + VKUtils.translateVulkanResult(err)); }
|
|
return descriptorSetLayout;
|
|
}
|
|
|
|
/*
|
|
* All resources that must be reallocated on window resize.
|
|
*/
|
|
private static Swapchain swapchain;
|
|
private static long[] framebuffers;
|
|
private static VkCommandBuffer[] renderCommandBuffers;
|
|
private static DepthStencil depthStencil;
|
|
|
|
public static void main(String[] args) throws IOException
|
|
{
|
|
Window.create(1200, 600, "Litecraft Vulkan", 60, RenderAPI.Vulkan);
|
|
new GingerVK();
|
|
VKRegister.exampleVKModel = new VKModelData();
|
|
/* Look for instance extensions */
|
|
PointerBuffer requiredExtensions = GLFWVulkan.glfwGetRequiredInstanceExtensions();
|
|
if (requiredExtensions == null)
|
|
{ throw new AssertionError("Failed to find list of required Vulkan extensions"); }
|
|
// Create the Vulkan instance
|
|
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);
|
|
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;
|
|
GLFW.glfwSetKeyCallback(Window.getWindow(), keyCallback = new GLFWKeyCallback()
|
|
{
|
|
public void invoke(long window, int key, int scancode, int action, int mods)
|
|
{
|
|
if (action != GLFW.GLFW_RELEASE)
|
|
return;
|
|
if (key == GLFW.GLFW_KEY_ESCAPE)
|
|
GLFW.glfwSetWindowShouldClose(window, true);
|
|
}
|
|
});
|
|
LongBuffer pSurface = MemoryUtil.memAllocLong(1);
|
|
int err = GLFWVulkan.glfwCreateWindowSurface(vulkanInstance, Window.getWindow(), null, pSurface);
|
|
final long surface = pSurface.get(0);
|
|
if (err != VK12.VK_SUCCESS)
|
|
{ throw new AssertionError("Failed to create surface: " + VKUtils.translateVulkanResult(err)); }
|
|
// Create static Vulkan resources
|
|
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 = RenderUtils.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;
|
|
|
|
void recreate()
|
|
{
|
|
// Begin the setup command buffer (the one we will use for swapchain/framebuffer creation)
|
|
VkCommandBufferBeginInfo cmdBufInfo = VkCommandBufferBeginInfo.calloc()
|
|
.sType(VK12.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO);
|
|
int err = VK12.vkBeginCommandBuffer(setupCommandBuffer, cmdBufInfo);
|
|
cmdBufInfo.free();
|
|
if (err != VK12.VK_SUCCESS)
|
|
{ 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(VKRegister.device, VKRegister.physicalDevice, surface, oldChain, setupCommandBuffer,
|
|
Window.getWidth(), Window.getHeight(), colorAndDepthFormatAndSpace.colorFormat, colorAndDepthFormatAndSpace.colorSpace);
|
|
// Create depth-stencil image
|
|
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(VKRegister.queue, setupCommandBuffer);
|
|
VK12.vkQueueWaitIdle(VKRegister.queue);
|
|
if (framebuffers != null)
|
|
{ for (int i = 0; i < framebuffers.length; i++)
|
|
VK12.vkDestroyFramebuffer(VKRegister.device, framebuffers[i], null); }
|
|
framebuffers = RenderUtils.createFramebuffers(VKRegister.device, swapchain, renderPass, Window.getWidth(), Window.getHeight(), depthStencil);
|
|
// Create render command buffers
|
|
if (renderCommandBuffers != null)
|
|
{ VK12.vkResetCommandPool(VKRegister.device, renderCommandPool, VKUtils.VK_FLAGS_NONE); }
|
|
renderCommandBuffers = VKUtils.setupRenderCommandBuffer(VKRegister.device, renderCommandPool, framebuffers, renderPass, Window.getWidth(), Window.getHeight(), pipeline, descriptorSet,
|
|
vertices.vkVerticiesBuffer);
|
|
mustRecreate = false;
|
|
}
|
|
}
|
|
final SwapchainRecreator swapchainRecreator = new SwapchainRecreator();
|
|
// Handle canvas resize
|
|
GLFWFramebufferSizeCallback framebufferSizeCallback = new GLFWFramebufferSizeCallback()
|
|
{
|
|
public void invoke(long window, int width, int height)
|
|
{
|
|
if (width <= 0 || height <= 0)
|
|
return;
|
|
swapchainRecreator.mustRecreate = true;
|
|
}
|
|
};
|
|
GLFW.glfwSetFramebufferSizeCallback(Window.getWindow(), framebufferSizeCallback);
|
|
GLFW.glfwShowWindow(Window.getWindow());
|
|
// Pre-allocate everything needed in the render loop
|
|
IntBuffer pImageIndex = MemoryUtil.memAllocInt(1);
|
|
int currentBuffer = 0;
|
|
PointerBuffer pCommandBuffers = MemoryUtil.memAllocPointer(1);
|
|
LongBuffer pSwapchains = MemoryUtil.memAllocLong(1);
|
|
LongBuffer pImageAcquiredSemaphore = MemoryUtil.memAllocLong(1);
|
|
LongBuffer pRenderCompleteSemaphore = MemoryUtil.memAllocLong(1);
|
|
// Info struct to create a semaphore
|
|
VkSemaphoreCreateInfo semaphoreCreateInfo = VkSemaphoreCreateInfo.calloc()
|
|
.sType(VK12.VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO);
|
|
// Info struct to submit a command buffer which will wait on the semaphore
|
|
IntBuffer pWaitDstStageMask = MemoryUtil.memAllocInt(1);
|
|
pWaitDstStageMask.put(0, VK12.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
|
VkSubmitInfo submitInfo = VkSubmitInfo.calloc()
|
|
.sType(VK12.VK_STRUCTURE_TYPE_SUBMIT_INFO)
|
|
.waitSemaphoreCount(pImageAcquiredSemaphore.remaining())
|
|
.pWaitSemaphores(pImageAcquiredSemaphore)
|
|
.pWaitDstStageMask(pWaitDstStageMask)
|
|
.pCommandBuffers(pCommandBuffers)
|
|
.pSignalSemaphores(pRenderCompleteSemaphore);
|
|
// Info struct to present the current swapchain image to the display
|
|
VkPresentInfoKHR presentInfo = VkPresentInfoKHR.calloc()
|
|
.sType(KHRSwapchain.VK_STRUCTURE_TYPE_PRESENT_INFO_KHR)
|
|
.pWaitSemaphores(pRenderCompleteSemaphore)
|
|
.swapchainCount(pSwapchains.remaining())
|
|
.pSwapchains(pSwapchains)
|
|
.pImageIndices(pImageIndex)
|
|
.pResults(null);
|
|
// The render loop
|
|
long lastTime = System.nanoTime();
|
|
float time = 0.0f;
|
|
while (!GLFW.glfwWindowShouldClose(Window.getWindow()))
|
|
{
|
|
Window.update();
|
|
if (swapchainRecreator.mustRecreate)
|
|
swapchainRecreator.recreate();
|
|
|
|
|
|
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(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(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)); }
|
|
// Select the command buffer for the current framebuffer image/attachment
|
|
pCommandBuffers.put(0, renderCommandBuffers[currentBuffer]);
|
|
// Update UBO
|
|
long thisTime = System.nanoTime();
|
|
time += (thisTime - lastTime) / 1E9f;
|
|
lastTime = thisTime;
|
|
ubo.updateUbo(VKRegister.device, time);
|
|
// Submit to the graphics queue
|
|
|
|
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(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(VKRegister.queue);
|
|
// Destroy this semaphore (we will create a new one in the next frame)
|
|
VK12.vkDestroySemaphore(VKRegister.device, pImageAcquiredSemaphore.get(0), null);
|
|
VK12.vkDestroySemaphore(VKRegister.device, pRenderCompleteSemaphore.get(0), null);
|
|
}
|
|
((GingerVK)GingerVK.getInstance()).end(pWaitDstStageMask, pImageAcquiredSemaphore, pRenderCompleteSemaphore, pSwapchains, pCommandBuffers, semaphoreCreateInfo, submitInfo, presentInfo, vulkanInstance, debugCallbackHandle, framebufferSizeCallback, keyCallback);
|
|
}
|
|
} |