0

I am loading a sample gltf 2.0 model into my Vulkan program using a custom parser, everything loads fine except that on this particular 3d model (which is a bath duck model found on gltf 2.0 github page), the beak of the duck seems to be failing the depth testing.

the duck should look like this

enter image description here

However in my program it looks like this enter image description here

here is the duck from another angle enter image description here

Note that i have not applied the projection matrix yet, and i am inverting the y component of the model matrix as well as setting my front face to counter clockwise

Vulkan pipeline initialization

  void phantom::createGraphicsPipeline()
  {
auto vertShaderCode = readFile("shaders/vert.spv");
auto fragShaderCode = readFile("shaders/frag.spv");

createShaderModule(vertShaderCode, vertShaderModule);
createShaderModule(fragShaderCode, fragShaderModule);

VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertShaderStageInfo.module = vertShaderModule;
vertShaderStageInfo.pName = "main";

VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragShaderStageInfo.module = fragShaderModule;
fragShaderStageInfo.pName = "main";

VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };

//auto bindingDescription = getBindingDescription();
//auto attributeDescription = getAttributeDescription();

VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = static_cast<uint32_t> (vertexBinding.size());
vertexInputInfo.pVertexBindingDescriptions = vertexBinding.data();
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertexAttributes.size());
vertexInputInfo.pVertexAttributeDescriptions = vertexAttributes.data();

VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;

VkViewport viewport = {};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float)swapChainExtend.width;
viewport.height = (float)swapChainExtend.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;

VkRect2D scissor = {};
scissor.offset = { 0,0 };
scissor.extent = swapChainExtend;

VkPipelineViewportStateCreateInfo viewportState = {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissor;

VkPipelineRasterizationStateCreateInfo rasterizer = {};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_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 = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f;
rasterizer.depthBiasClamp = 0.0f;
rasterizer.depthBiasSlopeFactor = 0.0f;

VkPipelineMultisampleStateCreateInfo multisampling = {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisampling.minSampleShading = 1.0f;
multisampling.pSampleMask = nullptr;
multisampling.alphaToCoverageEnable = VK_FALSE;
multisampling.alphaToOneEnable = VK_FALSE;

VkPipelineDepthStencilStateCreateInfo depthStencil = {};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f;
depthStencil.maxDepthBounds = 1.0f;
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front = {};
depthStencil.back = {};

VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = VK_FALSE;
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;

VkPipelineColorBlendStateCreateInfo colorBlending = {};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.logicOp = VK_LOGIC_OP_COPY;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f;
colorBlending.blendConstants[1] = 0.0f;
colorBlending.blendConstants[2] = 0.0f;
colorBlending.blendConstants[3] = 0.0f;

VkDynamicState dynamicStates[] = {
    VK_DYNAMIC_STATE_VIEWPORT,
    VK_DYNAMIC_STATE_LINE_WIDTH
};

VkPipelineDynamicStateCreateInfo dynamicState = {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = 2;
dynamicState.pDynamicStates = dynamicStates;

VkDescriptorSetLayout setLayouts[] = { descriptorSetLayout };

VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = setLayouts;
pipelineLayoutInfo.pushConstantRangeCount = 0;
pipelineLayoutInfo.pPushConstantRanges = 0;

if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS)
{
    throw std::runtime_error("failed to create pipeline layout !");
}

VkGraphicsPipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
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.pDynamicState = nullptr;
pipelineInfo.layout = pipelineLayout;
pipelineInfo.renderPass = renderPass;
pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineInfo.basePipelineIndex = -1;

if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS)
{
    throw std::runtime_error("failed to create graphics pipeline! ");
}
}

transformation matrix fed to the command buffer

glm::mat4 rotationMat = glm::rotate(10.f,glm::vec3(0,1,0));
glm::mat4 translateMat = glm::translate(glm::vec3(0, 0, 0));
glm::mat4 scaleMat = glm::scale(glm::vec3(30, 30, 30));
glm::mat4 modelMat = v.model.transformation[0] * scaleMat * rotationMat;
//v.model.transformation[0] = rotationMat * v.model.transformation[0];
modelMat[1][1] = modelMat[1][1] * -1;
v.updateUniformBuffer(modelMat);

depth resource and renderpass creation debug messages enter image description here

Render pass creation method

void phantom::createRenderPass()
{
std::cout << "entered renderpass creation" << std::endl;

VkAttachmentDescription colorAttachment = {};
colorAttachment.format = swapChainImageFormat;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

VkAttachmentReference colorAttachmentRef = {};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

VkAttachmentDescription depthAttachment = {};
depthAttachment.format = findDepthFormat();
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

VkAttachmentReference depthAttachmentRef = {};
depthAttachmentRef.attachment = 1;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;


VkSubpassDescription subPass = {};
subPass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subPass.colorAttachmentCount = 1;
subPass.pColorAttachments = &colorAttachmentRef;
subPass.pDepthStencilAttachment = &depthAttachmentRef;

std::vector <VkAttachmentDescription> attachments = { colorAttachment, depthAttachment };

VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = attachments.size();
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subPass;

VkSubpassDependency dependency = {};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependency.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency;

if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS)
{
    throw std::runtime_error("failed to create render pass ! ");
}


}

FrameBuffer Creation method

void phantom::createFrameBuffer()
{
swapChainFramebuffers.resize(swapChainImageViews.size());
for (size_t i = 0; i < swapChainImageViews.size(); i++)
{
    std::vector<VkImageView> attachments = { swapChainImageViews[i], depthImageView };

    VkFramebufferCreateInfo framebufferInfo = {};
    framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
    framebufferInfo.renderPass = renderPass;
    framebufferInfo.attachmentCount = attachments.size();
    framebufferInfo.pAttachments = attachments.data();
    framebufferInfo.width = swapChainExtend.width;
    framebufferInfo.height = swapChainExtend.height;
    framebufferInfo.layers = 1;

    if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS)
    {
        throw std::runtime_error("failed to create framebuffer!");
    }
}
}
BulBul
  • 1,159
  • 3
  • 24
  • 37
  • To me this does look like a depth test problem, paired with a skewed aspect ratio. What happens if you flip `depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;` to be greater instead of less? – emackey Mar 31 '18 at 15:50
  • @emackey when i set it to be greater it does not show anything at all, and whatever the setting configuration i tried it always has that problem, is there any other possibility that it might be caused by any other field other than depth testing? – BulBul Mar 31 '18 at 22:19
  • I see you invert y in ur glm matrix, did u also adjust z from -1/1 to 0/1. – yngccc Apr 01 '18 at 18:53
  • @yngccc yes i forced glm to re adjust z as 0 - 1 using `#define GLM_FORCE_DEPTH_ZERO_TO_ONE` at the top of my header file – BulBul Apr 01 '18 at 18:57

2 Answers2

1

gltf was designed with OpenGl in mind, thus it accepts (depth Values) of (-1 to 1), so whenever you want to use gltf with Vulkan you have to compensate for that since Vulkan expects depth range of (0 to 1).

in my example i was sending the vertex data to the shader in raw binary format, so technically i was not mapping the z value to the range required by Vulkan, i applied the required range mapping to the depth value and the problem is resolved.

here is the result of my program enter image description here

BulBul
  • 1,159
  • 3
  • 24
  • 37
0

Other bits of the mesh seem to be missing too (tail maybe? or is that just occluded?). My guess would be face culling rather than depth testing. Try rasterizer.cullMode == VK_CULL_MODE_NONE?

Jesse Hall
  • 6,441
  • 23
  • 29
  • the cull mode made things even worse, the tail is not missing its just that i have not fed the perspective projection matrix and my model is flattened by the applied transformation, i edited the question with a new view angle of the duck picture as well as the transformation matrix operations. – BulBul Mar 30 '18 at 12:15
  • Silly question - do You have depth attachment added to both a render pass and a framebuffer? Or maybe depth values are inverted - what is further away is treated as if it nearer the camera and vice versa. Try inverting depth setup in a viewport. – Ekzuzy Mar 30 '18 at 13:21
  • @Ekzuzy i tried to reverse the depth comparison operation, inverted the Z value, i even tried to use an identity matrix just to make sure it was not inverting coordinate values still the problem is not getting resolved, i updated the post with the debug messages regarding depth and renderpass stages. – BulBul Mar 31 '18 at 22:35
  • @BulBul Maybe show us render pass and framebuffer creation code. Debug messages doesn't show anything useful. There is a pipeline barrier problem but (unless it has something to do with layout transitions) it shouldn't have such impact. – Ekzuzy Apr 01 '18 at 08:54
  • @Ekzuzy i updated the question with the framebuffer and renderpass creation code. – BulBul Apr 01 '18 at 11:44
  • This looks fine. Could You share Your project somewhere (I hope it's for Windows)? I can debug it as I don't see anything wrong in the code parts You showed in the question. – Ekzuzy Apr 02 '18 at 06:47
  • @Ekzuzy you can find the project files as well as the dependent libraries [here](https://drive.google.com/open?id=1tqAaJAuTUYzVCTJ-SXVEGFsnMvaZ-kAi), kindly ignore the strange naming and messy code as this was intended to experiment on the vulkan gltf integration, I highly appreciate your help. – BulBul Apr 03 '18 at 08:51
  • @Ekzuzy i think i found a possible cause of this issue, I am sending the vertex attributes to the shader using raw binary data by which `#define GLM_FORCE_DEPTH_ZERO_TO_ONE` has no effect on it, i tried to map the vertex range -1 -> 1 to 0 -> 1 in the vertex shader something definitely improved but the problem was still there, is there any function to map a binary array to a vector of vec3? so that glm would automatically map the z value to the correct range. – BulBul Apr 04 '18 at 19:32
  • @BulBul It's great that You solved Your problem!! I'm sorry I didn't look into Your project. I had a very tough week and I, unfortunately, I didn't have time. :-( – Ekzuzy Apr 07 '18 at 17:33
  • 1
    @Ekzuzy there is nothing to be sorry about, i highly appreciate the time you took to help me on this issue, it was a great challenge for me to learn more about the behavior of vulkan and gltf so it is a double win :) – BulBul Apr 07 '18 at 17:56