I’m about to write a G-Buffer in Vulkan. As of now, I got two attachments in the framebuffer and render pass: albedo and depth. Albedo has index 0 and depth index 1.
Now, I’m trying to add another attachment for the world-space position. So albedo still has index 0, position now has index 1 and depth index 2. The albedo attachment still works as usual, e.g. my scene is being drawn into that attachment and depth testing is working. But the position attachment isn’t working as expected. Although the attachment is being cleared at the beginning of the render pass, nothing is being drawn into that attachment. I checked the examples by Sascha Willems for clues, but didn’t find any.
Here is my MRT fragment shader:
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(set = 1, binding = 0) uniform sampler2D diffuse;
layout(set = 1, binding = 1) uniform sampler2D normal;
layout(set = 1, binding = 2) uniform sampler2D specular;
layout(set = 1, binding = 3) uniform sampler2D emissive;
layout(location = 0) in vec2 texCoord;
layout(location = 1) in vec3 modelPosition;
layout(location = 2) in vec3 modelNormal;
layout(location = 0) out vec4 outDiffuse;
layout(location = 1) out vec4 outPosition;
void main() {
outDiffuse = vec4(texture(diffuse, texCoord).rgb, 1.0);
outPosition = vec4(texture(diffuse, texCoord).rgb, 1.0);
}
So I’m expecting the same image in the position attachment as in the albedo/diffuse attachment.
Here is the code where I’m creating the render pass (the formats and layouts are there for testing purposes):
std::vector<VkAttachmentReference> colorAttachmentRefs;
// diffuse
VkAttachmentDescription diffuseAttachment = {};
diffuseAttachment.format = VK_FORMAT_R8G8B8A8_UNORM;
diffuseAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
diffuseAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
diffuseAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
diffuseAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
diffuseAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
diffuseAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
diffuseAttachment.finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
attachments.push_back(diffuseAttachment);
VkAttachmentReference diffuseAttachmentRef = {};
diffuseAttachmentRef.attachment = GBUFFER_ATTACHMENT_DIFFUSE;
diffuseAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorAttachmentRefs.push_back(diffuseAttachmentRef);
VkAttachmentDescription positionAttachment = {};
positionAttachment.format = VK_FORMAT_R8G8B8A8_UNORM;
positionAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
positionAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
positionAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
positionAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
positionAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
positionAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
positionAttachment.finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
attachments.push_back(positionAttachment);
VkAttachmentReference positionAttachmentRef = {};
positionAttachmentRef.attachment = GBUFFER_ATTACHMENT_POSITION;
positionAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorAttachmentRefs.push_back(positionAttachmentRef);
// depth
VkAttachmentDescription depthAttachment = {};
depthAttachment.format = VK_FORMAT_D24_UNORM_S8_UINT;
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;
attachments.push_back(depthAttachment);
VkAttachmentReference depthAttachmentRef = {};
depthAttachmentRef.attachment = GBUFFER_ATTACHMENT_DEPTH;
depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDependency dependencies[2] = {};
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
VkSubpassDescription subPass = {};
subPass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subPass.colorAttachmentCount = colorAttachmentRefs.size();
subPass.pColorAttachments = colorAttachmentRefs.data();
subPass.pDepthStencilAttachment = &depthAttachmentRef;
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;
renderPassInfo.dependencyCount = 2;
renderPassInfo.pDependencies = dependencies;
if(vkCreateRenderPass(_vulkanCommon->device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS){
log::error("could not create render pass.");
return false;
}
“GBUFFER_ATTACHMENT_POSITION” is 1.
Do you guys have any clue why that attachment is being cleared, but now drawn to? Did I forget something?