267 lines
16 KiB
C++
267 lines
16 KiB
C++
#include "vulkan_graphics_pipeline.h"
|
|
#include "../shaders/vulkan_shader_module.h"
|
|
#include "vulkan_renderpass.h"
|
|
#include "../vertex_buffers/vertex_descriptions/vulkan_vertex_description.h"
|
|
#include "../uniform_descriptor/vulkan_uniform_layout.h"
|
|
#include "../push_constant/vulkan_push_constant.h"
|
|
|
|
void vulkanCreateGraphicsPipeline(gnGraphicsPipeline* pipeline) {
|
|
if (pipeline->graphicsPipeline == nullptr) pipeline->graphicsPipeline = new gnPlatformGraphicsPipeline();
|
|
|
|
pipeline->graphicsPipeline->inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
|
pipeline->graphicsPipeline->rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
|
pipeline->graphicsPipeline->rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
|
pipeline->graphicsPipeline->dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
|
pipeline->graphicsPipeline->viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
|
pipeline->graphicsPipeline->multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
|
pipeline->graphicsPipeline->colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
|
pipeline->graphicsPipeline->colorBlending.logicOpEnable = VK_FALSE;
|
|
pipeline->graphicsPipeline->colorBlending.attachmentCount = 1;
|
|
pipeline->graphicsPipeline->colorBlending.blendConstants[0] = 0.0f;
|
|
pipeline->graphicsPipeline->colorBlending.blendConstants[1] = 0.0f;
|
|
pipeline->graphicsPipeline->colorBlending.blendConstants[2] = 0.0f;
|
|
pipeline->graphicsPipeline->colorBlending.blendConstants[3] = 0.0f;
|
|
pipeline->graphicsPipeline->depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
|
pipeline->graphicsPipeline->pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
|
}
|
|
|
|
GN_EXPORT void gnGraphicsPipelineSetPrimativeFn(gnGraphicsPipeline& pipeline, gnPrimative primative) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.primative = primative;
|
|
|
|
if (primative == GN_POINTS) pipeline.graphicsPipeline->inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
|
|
else if (primative == GN_LINES) pipeline.graphicsPipeline->inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
|
else if (primative == GN_LINE_STRIP) pipeline.graphicsPipeline->inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
|
|
else if (primative == GN_TRIANGLES) pipeline.graphicsPipeline->inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
|
else { /* TODO: throw debugger runtime errors */ }
|
|
|
|
pipeline.graphicsPipeline->inputAssembly.primitiveRestartEnable = VK_FALSE;
|
|
}
|
|
|
|
GN_EXPORT void gnGraphicsPipelineEnableDynamicStatesFn(gnGraphicsPipeline& pipeline, const gnBool enable) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.graphicsPipeline->dynamicStatesEnabled = true;
|
|
|
|
pipeline.graphicsPipeline->dynamicState.dynamicStateCount = static_cast<uint32_t>(pipeline.graphicsPipeline->dynamicStates.size());
|
|
pipeline.graphicsPipeline->dynamicState.pDynamicStates = pipeline.graphicsPipeline->dynamicStates.data();
|
|
}
|
|
|
|
GN_EXPORT void gnGraphicsPipelineEnableDynamicStateFn(gnGraphicsPipeline& pipeline, const gnDynamicState state) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
VkDynamicState dynamicState;
|
|
if (state == GN_DYNAMIC_STATE_VIEWPORT) dynamicState = VK_DYNAMIC_STATE_VIEWPORT;
|
|
if (state == GN_DYNAMIC_STATE_SCISSOR) dynamicState = VK_DYNAMIC_STATE_SCISSOR;
|
|
pipeline.graphicsPipeline->dynamicStates.push_back(dynamicState);
|
|
}
|
|
|
|
GN_EXPORT void _gnGraphicsPipelineSetViewportFn(gnGraphicsPipeline& pipeline, gnUInt2 position, gnUInt2 size, gnFloat minDepth, gnFloat maxDepth) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.graphicsPipeline->viewport.x = position.x;
|
|
pipeline.graphicsPipeline->viewport.y = position.y;
|
|
pipeline.graphicsPipeline->viewport.width = (float)size.x;
|
|
pipeline.graphicsPipeline->viewport.height = (float)size.y;
|
|
pipeline.graphicsPipeline->viewport.minDepth = minDepth;
|
|
pipeline.graphicsPipeline->viewport.maxDepth = maxDepth;
|
|
pipeline.graphicsPipeline->viewportState.viewportCount = 1;
|
|
|
|
if (!pipeline.graphicsPipeline->dynamicStateEnabled(VK_DYNAMIC_STATE_VIEWPORT)) {
|
|
pipeline.graphicsPipeline->viewportState.pViewports = &pipeline.graphicsPipeline->viewport;
|
|
}
|
|
}
|
|
GN_EXPORT void gnGraphicsPipelineSetCropFn(gnGraphicsPipeline& pipeline, gnInt2 position, gnUInt2 size) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.graphicsPipeline->scissor.offset = { position.x, position.y };
|
|
pipeline.graphicsPipeline->scissor.extent = {size.x, size.y};
|
|
pipeline.graphicsPipeline->viewportState.scissorCount = 1;
|
|
|
|
if (!pipeline.graphicsPipeline->dynamicStateEnabled(VK_DYNAMIC_STATE_VIEWPORT)) {
|
|
pipeline.graphicsPipeline->viewportState.pScissors = &pipeline.graphicsPipeline->scissor;
|
|
}
|
|
}
|
|
GN_EXPORT void gnGraphicsPipelineSetDepthClampFn(gnGraphicsPipeline& pipeline, gnBool enableDepthClamp) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.graphicsPipeline->rasterizer.depthClampEnable = (enableDepthClamp == true) ? VK_TRUE : VK_FALSE;
|
|
}
|
|
GN_EXPORT void gnGraphicsPipelineSetFillModeFn(gnGraphicsPipeline& pipeline, gnFillMode fillMode) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
VkPolygonMode polygoneMode = VK_POLYGON_MODE_FILL;
|
|
if (fillMode == GN_POLYGON_FILLMODE_FILL) polygoneMode = VK_POLYGON_MODE_FILL;
|
|
if (fillMode == GN_POLYGON_FILLMODE_LINES) polygoneMode = VK_POLYGON_MODE_LINE;
|
|
if (fillMode == GN_POLYGON_FILLMODE_POINTS) polygoneMode = VK_POLYGON_MODE_POINT;
|
|
|
|
pipeline.graphicsPipeline->rasterizer.polygonMode = polygoneMode;
|
|
}
|
|
GN_EXPORT void gnGraphicsPipelineSetLineWidthFn(gnGraphicsPipeline& pipeline, gnFloat lineWidth) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.graphicsPipeline->rasterizer.lineWidth = lineWidth;
|
|
}
|
|
GN_EXPORT void gnGraphicsPipelineSetCullModeFn(gnGraphicsPipeline& pipeline, gnCullMode cullMode, gnFrontFaceDirection direction) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
VkCullModeFlags cullmode;
|
|
if(cullMode == GN_CULL_NONE) pipeline.graphicsPipeline->rasterizer.cullMode = VK_CULL_MODE_NONE;
|
|
else if(cullMode == GN_CULL_BACKFACE) pipeline.graphicsPipeline->rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
|
else if(cullMode == GN_CULL_FRONTFACE) pipeline.graphicsPipeline->rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
|
// else if(cullMode == GN_CULL_ALL) pipeline.graphicsPipeline->rasterizer.cullMode = VK_CULL_MODE_FRONT_AND_BACK;
|
|
|
|
pipeline.graphicsPipeline->rasterizer.frontFace = (direction == GN_CLOCKWISE) ? VK_FRONT_FACE_CLOCKWISE : VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
|
}
|
|
GN_EXPORT void gnGraphicsPipelineSetMultisamplingFn(gnGraphicsPipeline& pipeline, gnBool enableMultisampling) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
if (enableMultisampling) { /* TODO: Debugger needs to throw some errors */ return; }
|
|
|
|
pipeline.graphicsPipeline->multisampling.sampleShadingEnable = VK_FALSE;
|
|
pipeline.graphicsPipeline->multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
|
}
|
|
|
|
|
|
GN_EXPORT void gnGraphicsPipelineSetColorBlendFn(gnGraphicsPipeline& pipeline, gnBool colorBlend) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
// if (colorBlend) { /* TODO: Debugger needs to throw some errors */ return; }
|
|
|
|
pipeline.graphicsPipeline->colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
|
pipeline.graphicsPipeline->colorBlendAttachment.blendEnable = (colorBlend) ? VK_TRUE : VK_FALSE;
|
|
pipeline.graphicsPipeline->colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
|
pipeline.graphicsPipeline->colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
|
pipeline.graphicsPipeline->colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
|
|
pipeline.graphicsPipeline->colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
|
pipeline.graphicsPipeline->colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
|
pipeline.graphicsPipeline->colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
|
|
|
pipeline.graphicsPipeline->colorBlending.pAttachments = &pipeline.graphicsPipeline->colorBlendAttachment;
|
|
|
|
}
|
|
GN_EXPORT void gnGraphicsPipelineSetRenderPassFn(gnGraphicsPipeline& pipeline, gnRenderPass& renderpass) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.renderPass = &renderpass;
|
|
|
|
pipeline.graphicsPipeline->pipelineInfo.renderPass = renderpass.renderpass->renderPass;
|
|
pipeline.graphicsPipeline->pipelineInfo.subpass = 0;
|
|
}
|
|
|
|
GN_EXPORT void gnGraphicsPipelineBindShaderFn(gnGraphicsPipeline& pipeline, const gnShader& shader) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.graphicsPipeline->pipelineInfo.stageCount = gnListLength(shader.shaderModules);
|
|
|
|
for (int i = 0; i < gnListLength(shader.shaderModules); i++) {
|
|
pipeline.graphicsPipeline->shaderStages.push_back(shader.shaderModules[i].shaderModule->stageCreateInfo);
|
|
}
|
|
|
|
|
|
pipeline.graphicsPipeline->pipelineInfo.pStages = pipeline.graphicsPipeline->shaderStages.data();
|
|
}
|
|
|
|
GN_EXPORT void gnGraphicsPipelineSetVertexDescriptionFn(gnGraphicsPipeline& pipeline, const gnVertexDescription& vertexDescription) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.graphicsPipeline->vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
|
pipeline.graphicsPipeline->vertexInputInfo.vertexBindingDescriptionCount = 1;
|
|
pipeline.graphicsPipeline->vertexInputInfo.vertexAttributeDescriptionCount = vertexDescription.vertexDescription->attributeDescriptionCount;
|
|
pipeline.graphicsPipeline->vertexInputInfo.pVertexBindingDescriptions = &vertexDescription.vertexDescription->bindingDescription;
|
|
pipeline.graphicsPipeline->vertexInputInfo.pVertexAttributeDescriptions = vertexDescription.vertexDescription->attributeDescriptions;
|
|
}
|
|
|
|
GN_EXPORT void gnGraphicsPipelineEnableDepthTestFn(gnGraphicsPipeline& pipeline, gnBool depthTest) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
if (depthTest == true) {
|
|
pipeline.graphicsPipeline->depthStencil.depthTestEnable = (depthTest == true) ? VK_TRUE : VK_FALSE;
|
|
} else {
|
|
pipeline.graphicsPipeline->depthStencil.depthTestEnable = VK_FALSE;
|
|
}
|
|
pipeline.graphicsPipeline->depthStencil.depthWriteEnable = VK_TRUE;
|
|
pipeline.graphicsPipeline->depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
|
|
pipeline.graphicsPipeline->depthStencil.depthBoundsTestEnable = VK_FALSE;
|
|
pipeline.graphicsPipeline->depthStencil.minDepthBounds = 0.0f; // Optional
|
|
pipeline.graphicsPipeline->depthStencil.maxDepthBounds = 1.0f; // Optional
|
|
pipeline.graphicsPipeline->depthStencil.stencilTestEnable = VK_FALSE;
|
|
pipeline.graphicsPipeline->depthStencil.front = {}; // Optional
|
|
pipeline.graphicsPipeline->depthStencil.back = {}; // Optional
|
|
}
|
|
|
|
GN_EXPORT gnReturnCode gnCreateGraphicsPipelineFn(gnGraphicsPipeline* pipeline, gnOutputDevice& outputDevice) {
|
|
vulkanCreateGraphicsPipeline(pipeline);
|
|
pipeline->graphicsPipeline->commandPool = &outputDevice.outputDevice->commandPool;
|
|
|
|
std::vector<VkDescriptorSetLayout> descriptorLayouts;
|
|
for (int i = 0; i < pipeline->uniformLayouts.size(); i++) {
|
|
descriptorLayouts.push_back(pipeline->uniformLayouts[i]->uniformLayout->setLayout);
|
|
}
|
|
|
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
|
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
pipelineLayoutInfo.setLayoutCount = static_cast<uint32_t>(pipeline->uniformLayouts.size());
|
|
pipelineLayoutInfo.pSetLayouts = descriptorLayouts.data();
|
|
|
|
std::vector<VkPushConstantRange> pushConstantRanges = {};
|
|
for (int i = 0; i < pipeline->pushConstants.size(); i++ ) {
|
|
VkPushConstantRange range;
|
|
|
|
range.offset = pipeline->pushConstants[i]->offset;
|
|
range.size = pipeline->pushConstants[i]->size;
|
|
|
|
int stageBit = 0;
|
|
|
|
if (gnContainsShaderStage(pipeline->pushConstants[i]->stage, GN_VERTEX_SHADER_MODULE)) stageBit |= VK_SHADER_STAGE_VERTEX_BIT;
|
|
if (gnContainsShaderStage(pipeline->pushConstants[i]->stage, GN_FRAGMENT_SHADER_MODULE)) stageBit |= VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
range.stageFlags = stageBit;
|
|
|
|
pushConstantRanges.push_back(range);
|
|
}
|
|
|
|
pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data();
|
|
pipelineLayoutInfo.pushConstantRangeCount = pipeline->pushConstants.size();
|
|
|
|
if (vkCreatePipelineLayout(outputDevice.outputDevice->device, &pipelineLayoutInfo, nullptr, &pipeline->graphicsPipeline->pipelineLayout) != VK_SUCCESS) {
|
|
return GN_FAILED;
|
|
}
|
|
|
|
for (int i = 0; i < pipeline->pushConstants.size(); i++ ) {
|
|
if (pipeline->pushConstants[i]->pushConstant == nullptr) { pipeline->pushConstants[i]->pushConstant = new gnPlatformPushConstant(); }
|
|
pipeline->pushConstants[i]->pushConstant->pushConstantRange = pushConstantRanges[i];
|
|
pipeline->pushConstants[i]->pushConstant->graphicsPipeline = pipeline;
|
|
}
|
|
|
|
pipeline->graphicsPipeline->outputDevice = &outputDevice;
|
|
|
|
{
|
|
pipeline->graphicsPipeline->pipelineInfo.pVertexInputState = &pipeline->graphicsPipeline->vertexInputInfo;
|
|
pipeline->graphicsPipeline->pipelineInfo.pInputAssemblyState = &pipeline->graphicsPipeline->inputAssembly;
|
|
pipeline->graphicsPipeline->pipelineInfo.pViewportState = &pipeline->graphicsPipeline->viewportState;
|
|
pipeline->graphicsPipeline->pipelineInfo.pRasterizationState = &pipeline->graphicsPipeline->rasterizer;
|
|
pipeline->graphicsPipeline->pipelineInfo.pMultisampleState = &pipeline->graphicsPipeline->multisampling;
|
|
pipeline->graphicsPipeline->pipelineInfo.pDepthStencilState = nullptr; // Optional
|
|
pipeline->graphicsPipeline->pipelineInfo.pColorBlendState = &pipeline->graphicsPipeline->colorBlending;
|
|
pipeline->graphicsPipeline->pipelineInfo.pDynamicState = &pipeline->graphicsPipeline->dynamicState;
|
|
pipeline->graphicsPipeline->pipelineInfo.pDepthStencilState = &pipeline->graphicsPipeline->depthStencil;
|
|
|
|
pipeline->graphicsPipeline->pipelineInfo.layout = pipeline->graphicsPipeline->pipelineLayout;
|
|
|
|
// for (int i = 0; i < pipeline->descriptorSet->descriptorSet->descriptorSets.size(); i++) {
|
|
// (*pipeline->uniformBufferDescriptors)[i].bufferDescription->descriptorSet = pipeline->descriptorSet->descriptorSet->descriptorSets[i];
|
|
// }
|
|
|
|
if (vkCreateGraphicsPipelines(outputDevice.outputDevice->device, VK_NULL_HANDLE, 1, &pipeline->graphicsPipeline->pipelineInfo, nullptr, &pipeline->graphicsPipeline->graphicsPipeline) != VK_SUCCESS) {
|
|
return GN_FAILED;
|
|
}
|
|
|
|
}
|
|
|
|
return GN_SUCCESS;
|
|
}
|
|
GN_EXPORT void gnGraphicsPipelineAddPushConstantFn(gnGraphicsPipeline& pipeline, const gnPushConstant& pushConstant) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.pushConstants.push_back(const_cast<gnPushConstant*>(&pushConstant));
|
|
}
|
|
GN_EXPORT void gnGraphicsPipelineSetUniformBufferDescriptorsFn(gnGraphicsPipeline& pipeline, const std::vector<gnBufferDescription>& bufferDescriptions) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
//graphicsPipeline.uniformBufferDescriptors = const_cast<std::vector<gnBufferDescription>*>(&bufferDescriptions);
|
|
}
|
|
GN_EXPORT void gnGraphicsPipelineAddUniformLayoutFn(gnGraphicsPipeline& pipeline, const gnUniformLayout& uniformLayout) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
pipeline.uniformLayouts.push_back(const_cast<gnUniformLayout*>(&uniformLayout));
|
|
}
|
|
GN_EXPORT void gnDestroyGraphicsPipelineFn(gnGraphicsPipeline& pipeline) {
|
|
vulkanCreateGraphicsPipeline(&pipeline);
|
|
vkDestroyPipeline(pipeline.graphicsPipeline->outputDevice->outputDevice->device, pipeline.graphicsPipeline->graphicsPipeline, nullptr);
|
|
vkDestroyPipelineLayout(pipeline.graphicsPipeline->outputDevice->outputDevice->device, pipeline.graphicsPipeline->pipelineLayout, nullptr);
|
|
}
|