I'm trying to get into Vulkan, but I'm running into some issues. My application (GitHub repo) is supposed to render a red triangle in the center of the screen. However, each time I run it, I get one of five different results instead of the expected output.
It seems like there are multiple validation layer errors related to pipeline creation. I suspect this is the root cause, but I'm not sure where to start .
I'm using 6.13.6-arch1-1. My graphics card is Intel Corporation TigerLake-LP GT2 [Iris Xe Graphics]. It's an integrated graphics card.
The error is definitely happens here:
void App::drawFrame()
{
uint32_t imageIndex;
auto result = tveSwapChain.acquireNextImage(&imageIndex);
if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
{
throw std::runtime_error("Failed to acquire swap chain image");
}
result = tveSwapChain.submitCommandBuffers(&commandBuffers[imageIndex], &imageIndex);
if(result != VK_SUCCESS)
{
throw std::runtime_error("Failed to present swap chain image");
}
}
Or here:
void TvePipeline::createGraphicsPipeline(const TveDevice &device, const std::string &vertFilepath,
const std::string &fragFilepath, const PipelineConfigInfo &configInfo)
{
assert(configInfo.pipelineLayout != VK_NULL_HANDLE &&
"Cannot create graphics pipeline: no pipelineLayout provided in configInfo.");
assert(configInfo.renderPass != VK_NULL_HANDLE &&
"Cannot create graphics pipeline: no renderPass provided in configInfo.");
auto vertCode = readFile(vertFilepath);
auto fragCode = readFile(fragFilepath);
createShaderModule(vertCode, &vertShaderModule);
createShaderModule(fragCode, &fragShaderModule);
VkPipelineShaderStageCreateInfo shaderStages[2];
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shaderStages[0].module = vertShaderModule;
shaderStages[0].pName = "main";
shaderStages[0].flags = 0;
shaderStages[0].pNext = nullptr;
shaderStages[0].pSpecializationInfo = nullptr;
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shaderStages[1].module = fragShaderModule;
shaderStages[1].pName = "main";
shaderStages[1].flags = 0;
shaderStages[1].pNext = nullptr;
shaderStages[1].pSpecializationInfo = nullptr;
VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexAttributeDescriptionCount = 0;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.pVertexAttributeDescriptions = nullptr;
vertexInputInfo.pVertexBindingDescriptions = nullptr;
VkPipelineViewportStateCreateInfo viewportInfo{};
viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportInfo.viewportCount = 1;
viewportInfo.pViewports = &configInfo.viewport;
viewportInfo.scissorCount = 1;
viewportInfo.pScissors = &configInfo.scissor;
VkGraphicsPipelineCreateInfo pipelineInfo;
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &configInfo.inputAssemblyInfo;
pipelineInfo.pViewportState = &viewportInfo;
pipelineInfo.pRasterizationState = &configInfo.rasterizationInfo;
pipelineInfo.pMultisampleState = &configInfo.multisampleInfo;
pipelineInfo.pColorBlendState = &configInfo.colorBlendInfo;
pipelineInfo.pDepthStencilState = &configInfo.depthStencilInfo;
pipelineInfo.pDynamicState = nullptr;
pipelineInfo.layout = configInfo.pipelineLayout;
pipelineInfo.renderPass = configInfo.renderPass;
pipelineInfo.subpass = configInfo.subpass;
pipelineInfo.basePipelineIndex = -1;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
if (vkCreateGraphicsPipelines(tveDevice.device(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) !=
VK_SUCCESS)
{
throw std::runtime_error("Failed to create graphics pipeline");
}
}
Start with zero-initializing your pipelineInfo
structure. You currently don't do that and you don't explicitly initiaize all fields. One field that you don't initialize is pNext
, so in your case that field can have any value. And since pNext
is a pointer, the layers and/or drivers try to dereference that random value which might explain your issues.
In general, (zero)initialize all you structures.