Ginger3D/src/main/java/com/github/hydos/ginger/engine/vulkan/render/pipelines/VKPipelineManager.java

212 lines
11 KiB
Java

package com.github.hydos.ginger.engine.vulkan.render.pipelines;
import static org.lwjgl.system.MemoryStack.stackPush;
import static org.lwjgl.vulkan.VK10.VK_COLOR_COMPONENT_A_BIT;
import static org.lwjgl.vulkan.VK10.VK_COLOR_COMPONENT_B_BIT;
import static org.lwjgl.vulkan.VK10.VK_COLOR_COMPONENT_G_BIT;
import static org.lwjgl.vulkan.VK10.VK_COLOR_COMPONENT_R_BIT;
import static org.lwjgl.vulkan.VK10.VK_COMPARE_OP_LESS;
import static org.lwjgl.vulkan.VK10.VK_CULL_MODE_BACK_BIT;
import static org.lwjgl.vulkan.VK10.VK_FRONT_FACE_COUNTER_CLOCKWISE;
import static org.lwjgl.vulkan.VK10.VK_LOGIC_OP_COPY;
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_SHADER_STAGE_FRAGMENT_BIT;
import static org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_VERTEX_BIT;
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_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_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_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 static org.lwjgl.vulkan.VK10.vkDestroyShaderModule;
import java.nio.ByteBuffer;
import java.nio.LongBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.VkGraphicsPipelineCreateInfo;
import org.lwjgl.vulkan.VkOffset2D;
import org.lwjgl.vulkan.VkPipelineColorBlendAttachmentState;
import org.lwjgl.vulkan.VkPipelineColorBlendStateCreateInfo;
import org.lwjgl.vulkan.VkPipelineDepthStencilStateCreateInfo;
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 org.lwjgl.vulkan.VkRect2D;
import org.lwjgl.vulkan.VkViewport;
import com.github.hydos.ginger.engine.vulkan.VKVariables;
import com.github.hydos.ginger.engine.vulkan.model.VKVertex;
import com.github.hydos.ginger.engine.vulkan.shaders.VKShaderManager;
import com.github.hydos.ginger.engine.vulkan.shaders.VKShaderUtils;
import com.github.hydos.ginger.engine.vulkan.shaders.VKShaderUtils.SPIRV;
public class VKPipelineManager
{
public static void createGraphicsPipeline() {
try(MemoryStack stack = stackPush()) {
SPIRV vertShaderSPIRV = VKShaderUtils.compileShaderFile("vulkan/shaders/entity.vert", VKShaderUtils.ShaderType.VERTEX_SHADER);
SPIRV fragShaderSPIRV = VKShaderUtils.compileShaderFile("vulkan/shaders/entity.frag", VKShaderUtils.ShaderType.FRAGMENT_SHADER);
long vertShaderModule = VKShaderManager.createShaderModule(vertShaderSPIRV.bytecode());
long fragShaderModule = VKShaderManager.createShaderModule(fragShaderSPIRV.bytecode());
ByteBuffer entryPoint = stack.UTF8("main");
VkPipelineShaderStageCreateInfo.Buffer shaderStages = VkPipelineShaderStageCreateInfo.callocStack(2, stack);
VkPipelineShaderStageCreateInfo vertShaderStageInfo = shaderStages.get(0);
vertShaderStageInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO);
vertShaderStageInfo.stage(VK_SHADER_STAGE_VERTEX_BIT);
vertShaderStageInfo.module(vertShaderModule);
vertShaderStageInfo.pName(entryPoint);
VkPipelineShaderStageCreateInfo fragShaderStageInfo = shaderStages.get(1);
fragShaderStageInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO);
fragShaderStageInfo.stage(VK_SHADER_STAGE_FRAGMENT_BIT);
fragShaderStageInfo.module(fragShaderModule);
fragShaderStageInfo.pName(entryPoint);
// VERTEX STAGE
VkPipelineVertexInputStateCreateInfo vertexInputInfo = VkPipelineVertexInputStateCreateInfo.callocStack(stack);
vertexInputInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO);
vertexInputInfo.pVertexBindingDescriptions(VKVertex.getBindingDescription());
vertexInputInfo.pVertexAttributeDescriptions(VKVertex.getAttributeDescriptions());
// ASSEMBLY STAGE
VkPipelineInputAssemblyStateCreateInfo inputAssembly = VkPipelineInputAssemblyStateCreateInfo.callocStack(stack);
inputAssembly.sType(VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO);
inputAssembly.topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
inputAssembly.primitiveRestartEnable(false);
// VIEWPORT & SCISSOR
VkViewport.Buffer viewport = VkViewport.callocStack(1, stack);
viewport.x(0.0f);
viewport.y(0.0f);
viewport.width(VKVariables .swapChainExtent.width());
viewport.height(VKVariables.swapChainExtent.height());
viewport.minDepth(0.0f);
viewport.maxDepth(1.0f);
VkRect2D.Buffer scissor = VkRect2D.callocStack(1, stack);
scissor.offset(VkOffset2D.callocStack(stack).set(0, 0));
scissor.extent(VKVariables.swapChainExtent);
VkPipelineViewportStateCreateInfo viewportState = VkPipelineViewportStateCreateInfo.callocStack(stack);
viewportState.sType(VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO);
viewportState.pViewports(viewport);
viewportState.pScissors(scissor);
// RASTERIZATION STAGE
VkPipelineRasterizationStateCreateInfo rasterizer = VkPipelineRasterizationStateCreateInfo.callocStack(stack);
rasterizer.sType(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO);
rasterizer.depthClampEnable(false);
rasterizer.rasterizerDiscardEnable(false);
rasterizer.polygonMode(VK_POLYGON_MODE_FILL);
rasterizer.lineWidth(1.0f);
rasterizer.cullMode(VK_CULL_MODE_BACK_BIT);
rasterizer.frontFace(VK_FRONT_FACE_COUNTER_CLOCKWISE);
rasterizer.depthBiasEnable(false);
// MULTISAMPLING
VkPipelineMultisampleStateCreateInfo multisampling = VkPipelineMultisampleStateCreateInfo.callocStack(stack);
multisampling.sType(VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO);
multisampling.sampleShadingEnable(true);
multisampling.minSampleShading(0.2f); // Enable sample shading in the pipeline
multisampling.rasterizationSamples(VKVariables.msaaSamples); // Min fraction for sample shading; closer to one is smoother
VkPipelineDepthStencilStateCreateInfo depthStencil = VkPipelineDepthStencilStateCreateInfo.callocStack(stack);
depthStencil.sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO);
depthStencil.depthTestEnable(true);
depthStencil.depthWriteEnable(true);
depthStencil.depthCompareOp(VK_COMPARE_OP_LESS);
depthStencil.depthBoundsTestEnable(false);
depthStencil.minDepthBounds(0.0f);
depthStencil.maxDepthBounds(1.0f);
depthStencil.stencilTestEnable(false);
// COLOR BLENDING
VkPipelineColorBlendAttachmentState.Buffer colorBlendAttachment = VkPipelineColorBlendAttachmentState.callocStack(1, stack);
colorBlendAttachment.colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
colorBlendAttachment.blendEnable(false);
VkPipelineColorBlendStateCreateInfo colorBlending = VkPipelineColorBlendStateCreateInfo.callocStack(stack);
colorBlending.sType(VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO);
colorBlending.logicOpEnable(false);
colorBlending.logicOp(VK_LOGIC_OP_COPY);
colorBlending.pAttachments(colorBlendAttachment);
colorBlending.blendConstants(stack.floats(0.0f, 0.0f, 0.0f, 0.0f));
// PIPELINE LAYOUT CREATION
VkPipelineLayoutCreateInfo pipelineLayoutInfo = VkPipelineLayoutCreateInfo.callocStack(stack);
pipelineLayoutInfo.sType(VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
pipelineLayoutInfo.pSetLayouts(stack.longs(VKVariables.descriptorSetLayout));
LongBuffer pPipelineLayout = stack.longs(VK_NULL_HANDLE);
if(vkCreatePipelineLayout(VKVariables.device, pipelineLayoutInfo, null, pPipelineLayout) != VK_SUCCESS) {
throw new RuntimeException("Failed to create pipeline layout");
}
VKVariables.pipelineLayout = pPipelineLayout.get(0);
VkGraphicsPipelineCreateInfo.Buffer pipelineInfo = VkGraphicsPipelineCreateInfo.callocStack(1, stack);
pipelineInfo.sType(VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
pipelineInfo.pStages(shaderStages);
pipelineInfo.pVertexInputState(vertexInputInfo);
pipelineInfo.pInputAssemblyState(inputAssembly);
pipelineInfo.pViewportState(viewportState);
pipelineInfo.pRasterizationState(rasterizer);
pipelineInfo.pMultisampleState(multisampling);
pipelineInfo.pDepthStencilState(depthStencil);
pipelineInfo.pColorBlendState(colorBlending);
pipelineInfo.layout(VKVariables.pipelineLayout);
pipelineInfo.renderPass(VKVariables.renderPass);
pipelineInfo.subpass(0);
pipelineInfo.basePipelineHandle(VK_NULL_HANDLE);
pipelineInfo.basePipelineIndex(-1);
LongBuffer pGraphicsPipeline = stack.mallocLong(1);
if(vkCreateGraphicsPipelines(VKVariables.device, VK_NULL_HANDLE, pipelineInfo, null, pGraphicsPipeline) != VK_SUCCESS) {
throw new RuntimeException("Failed to create graphics pipeline");
}
VKVariables.graphicsPipeline = pGraphicsPipeline.get(0);
// Cleanup
vkDestroyShaderModule(VKVariables.device, vertShaderModule, null);
vkDestroyShaderModule(VKVariables.device, fragShaderModule, null);
vertShaderSPIRV.free();
fragShaderSPIRV.free();
}
}
}