I am writing a graphics renderer using Vulkan in C++. I am currently trying to implement subpasses in the renderpass, but one of the fragment shaders is not properly written for subpasses and needs to be modified. Can you modify the Lighting Fragment Shader to correctly align with the rest of the code provided below?

Lighting Fragment Shader:

#version 450

layout(location = 0) out vec4 outColor;

layout(binding = 0) uniform sampler2D gPosition;
layout(binding = 1) uniform sampler2D gNormal;
layout(binding = 2) uniform sampler2D gAlbedo;

layout(location = 0) in vec2 fragTexCoord;

layout(set = 0, binding = 3) uniform Ambient_Data {
    vec3 color;
    float intensity;
} ambient;

layout(set = 0, binding = 4) uniform Directional_Data {
    vec3 position;
    vec3 color;
    float intensity;
} directional;

void main() {
    vec3 fragPosition = texture(gPosition, fragTexCoord).xyz;
    vec3 fragNormal = normalize(texture(gNormal, fragTexCoord).xyz);
    vec3 fragAlbedo = texture(gAlbedo, fragTexCoord).rgb;

    vec3 ambientLight = ambient.intensity * ambient.color;

    vec3 lightDir = normalize(directional.position - fragPosition);
    float diff = max(dot(fragNormal, lightDir), 0.0);
    vec3 diffuse = diff * directional.color;

    outColor = vec4((ambientLight + diffuse) * fragAlbedo, 1.0);
}

Renderpass code:

void Renderer::CreateRenderPass()
{
    vk::AttachmentDescription positionAttachment{};
    positionAttachment.format = vk::Format::eR16G16B16A16Sfloat; // High precision format
    positionAttachment.samples = vk::SampleCountFlagBits::e1;
    positionAttachment.loadOp = vk::AttachmentLoadOp::eClear;
    positionAttachment.storeOp = vk::AttachmentStoreOp::eStore;
    positionAttachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
    positionAttachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
    positionAttachment.initialLayout = vk::ImageLayout::eUndefined;
    positionAttachment.finalLayout = vk::ImageLayout::eShaderReadOnlyOptimal;

    vk::AttachmentDescription normalAttachment = positionAttachment;
    normalAttachment.format = vk::Format::eR16G16B16A16Sfloat;

    vk::AttachmentDescription albedoAttachment = positionAttachment;
    albedoAttachment.format = swapChainImageFormat; // Assuming albedo might use swap chain format

    vk::AttachmentDescription depthAttachment = positionAttachment;
    depthAttachment.format = FindDepthFormat(*GetPhysicalDevice());
    depthAttachment.samples = msaaSamples;
    depthAttachment.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;

    vk::AttachmentDescription colorAttachmentResolve{};
    colorAttachmentResolve.format = swapChainImageFormat;
    colorAttachmentResolve.samples = vk::SampleCountFlagBits::e1;
    colorAttachmentResolve.loadOp = vk::AttachmentLoadOp::eClear;
    colorAttachmentResolve.storeOp = vk::AttachmentStoreOp::eStore;
    colorAttachmentResolve.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
    colorAttachmentResolve.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
    colorAttachmentResolve.initialLayout = vk::ImageLayout::eUndefined;
    colorAttachmentResolve.finalLayout = vk::ImageLayout::ePresentSrcKHR;

    std::array<vk::AttachmentDescription, 5> attachments = {
        positionAttachment, normalAttachment, albedoAttachment, depthAttachment, colorAttachmentResolve
    };

    vk::AttachmentReference positionAttachmentRef{};
    positionAttachmentRef.attachment = 0;
    positionAttachmentRef.layout = vk::ImageLayout::eColorAttachmentOptimal;

    vk::AttachmentReference normalAttachmentRef{};
    normalAttachmentRef.attachment = 1;
    normalAttachmentRef.layout = vk::ImageLayout::eColorAttachmentOptimal;

    vk::AttachmentReference albedoAttachmentRef{};
    albedoAttachmentRef.attachment = 2;
    albedoAttachmentRef.layout = vk::ImageLayout::eColorAttachmentOptimal;

    vk::AttachmentReference depthAttachmentRef{};
    depthAttachmentRef.attachment = 3;
    depthAttachmentRef.layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;

    vk::AttachmentReference colorAttachmentResolveRef{};
    colorAttachmentResolveRef.attachment = 4;
    colorAttachmentResolveRef.layout = vk::ImageLayout::eColorAttachmentOptimal;

    std::array<vk::AttachmentReference, 3> colorAttachments = {
        positionAttachmentRef, normalAttachmentRef, albedoAttachmentRef
    };

    vk::SubpassDescription geometryPass{};
    geometryPass.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
    geometryPass.colorAttachmentCount = static_cast<uint32_t>(colorAttachments.size());
    geometryPass.pColorAttachments = colorAttachments.data();
    geometryPass.pDepthStencilAttachment = &depthAttachmentRef;

    vk::AttachmentReference colorAttachmentFinalRef{};
    colorAttachmentFinalRef.attachment = 4;
    colorAttachmentFinalRef.layout = vk::ImageLayout::eColorAttachmentOptimal;

    vk::SubpassDescription lightingPass{};
    lightingPass.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
    lightingPass.colorAttachmentCount = 1;
    lightingPass.pColorAttachments = &colorAttachmentFinalRef;

    std::array<vk::SubpassDescription, 2> subpasses = { geometryPass, lightingPass };

    // Define subpass dependencies
    vk::SubpassDependency externalToGeometryDependency{};
    externalToGeometryDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
    externalToGeometryDependency.dstSubpass = 0;
    externalToGeometryDependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
    externalToGeometryDependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
    externalToGeometryDependency.srcAccessMask = {};
    externalToGeometryDependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;

    vk::SubpassDependency geometryToLightingDependency{};
    geometryToLightingDependency.srcSubpass = 0;
    geometryToLightingDependency.dstSubpass = 1;
    geometryToLightingDependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
    geometryToLightingDependency.dstStageMask = vk::PipelineStageFlagBits::eFragmentShader;
    geometryToLightingDependency.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
    geometryToLightingDependency.dstAccessMask = vk::AccessFlagBits::eShaderRead;
    geometryToLightingDependency.dependencyFlags = vk::DependencyFlagBits::eByRegion;

    vk::SubpassDependency geometryToLightingDepthDependency{};
    geometryToLightingDepthDependency.srcSubpass = 0;
    geometryToLightingDepthDependency.dstSubpass = 1;
    geometryToLightingDepthDependency.srcStageMask = vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests;
    geometryToLightingDepthDependency.dstStageMask = vk::PipelineStageFlagBits::eFragmentShader;
    geometryToLightingDepthDependency.srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite;
    geometryToLightingDepthDependency.dstAccessMask = vk::AccessFlagBits::eShaderRead;
    geometryToLightingDepthDependency.dependencyFlags = vk::DependencyFlagBits::eByRegion;

    std::array<vk::SubpassDependency, 3> dependencies = {
        externalToGeometryDependency,
        geometryToLightingDependency,
        geometryToLightingDepthDependency
    };

    vk::RenderPassCreateInfo renderPassInfo{};
    renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
    renderPassInfo.pAttachments = attachments.data();
    renderPassInfo.subpassCount = static_cast<uint32_t>(subpasses.size());
    renderPassInfo.pSubpasses = subpasses.data();
    renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
    renderPassInfo.pDependencies = dependencies.data();

    if (device.createRenderPass(&renderPassInfo, nullptr, &renderPass) != vk::Result::eSuccess)
    {
        throw std::runtime_error("Failed to create render pass.");
    }
}

Geometry DescriptorSet code:

void Engine::CreateGeomDescriptorSet(vk::Device device, std::vector<VkBuffer> buffers, vk::DeviceSize bufferSize, vk::UniqueDescriptorPool& descriptorPool, Texture* texture, vk::DescriptorSetLayout descriptorSetLayout) {
	vk::DescriptorSetAllocateInfo allocInfo{};
	allocInfo.setDescriptorPool(descriptorPool.get());
	allocInfo.setDescriptorSetCount(1);
	allocInfo.setPSetLayouts(&descriptorSetLayout);

	geomdescriptorSet = std::move(device.allocateDescriptorSetsUnique(allocInfo)[0]);

	if (!geomdescriptorSet) {
		throw std::runtime_error("Failed to allocate descriptor set!");
	}

	vk::DescriptorBufferInfo bufferInfo1{};
	bufferInfo1.buffer = buffers[0];
	bufferInfo1.offset = 0;
	bufferInfo1.range = bufferSize * modelcount;

	vk::DescriptorBufferInfo bufferInfo2{};
	bufferInfo2.buffer = buffers[1];
	bufferInfo2.offset = 0;
	bufferInfo2.range = bufferSize;

	vk::DescriptorBufferInfo bufferInfo3{};
	bufferInfo3.buffer = buffers[2];
	bufferInfo3.offset = 0;
	bufferInfo3.range = bufferSize;

	vk::DescriptorImageInfo imageInfo{};
	imageInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
	imageInfo.imageView = texture->GetImageView();
	imageInfo.sampler = texture->GetSampler();


	std::array<vk::WriteDescriptorSet, 4> descriptorWrites{};

	descriptorWrites[0].setDstSet(geomdescriptorSet.get());
	descriptorWrites[0].setDstBinding(0);
	descriptorWrites[0].setDstArrayElement(0);
	descriptorWrites[0].setDescriptorType(vk::DescriptorType::eStorageBuffer);
	descriptorWrites[0].setDescriptorCount(1);
	descriptorWrites[0].setPBufferInfo(&bufferInfo1);

	descriptorWrites[1].setDstSet(geomdescriptorSet.get());
	descriptorWrites[1].setDstBinding(1);
	descriptorWrites[1].setDstArrayElement(0);
	descriptorWrites[1].setDescriptorType(vk::DescriptorType::eUniformBuffer);
	descriptorWrites[1].setDescriptorCount(1);
	descriptorWrites[1].setPBufferInfo(&bufferInfo2);

	descriptorWrites[2].setDstSet(geomdescriptorSet.get());
	descriptorWrites[2].setDstBinding(2);
	descriptorWrites[2].setDstArrayElement(0);
	descriptorWrites[2].setDescriptorType(vk::DescriptorType::eUniformBuffer);
	descriptorWrites[2].setDescriptorCount(1);
	descriptorWrites[2].setPBufferInfo(&bufferInfo3);

	descriptorWrites[3].setDstSet(geomdescriptorSet.get());
	descriptorWrites[3].setDstBinding(3);
	descriptorWrites[3].setDstArrayElement(0);
	descriptorWrites[3].setDescriptorType(vk::DescriptorType::eCombinedImageSampler);
	descriptorWrites[3].setDescriptorCount(1);
	descriptorWrites[3].setPImageInfo(&imageInfo);


	device.updateDescriptorSets(static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
}

Lighting DescriptorSet code:

void Engine::CreateLightDescriptorSet(Renderer* renderer, vk::Device device, std::vector<VkBuffer> buffers, vk::DeviceSize bufferSize, vk::UniqueDescriptorPool& descriptorPool, Texture* texture, vk::DescriptorSetLayout descriptorSetLayout) {
	vk::DescriptorSetAllocateInfo allocInfo{};
	allocInfo.setDescriptorPool(descriptorPool.get());
	allocInfo.setDescriptorSetCount(1);
	allocInfo.setPSetLayouts(&descriptorSetLayout);

	lightdescriptorSet = std::move(device.allocateDescriptorSetsUnique(allocInfo)[0]);

	if (!lightdescriptorSet) {
		throw std::runtime_error("Failed to allocate descriptor set!");
	}

	vk::DescriptorImageInfo positionTextureInfo{};
	positionTextureInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
	positionTextureInfo.imageView = renderer->positionImageView;//texture->GetImageView();
	positionTextureInfo.sampler = texture->GetSampler();

	vk::DescriptorImageInfo normalTextureInfo{};
	normalTextureInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
	normalTextureInfo.imageView = renderer->normalImageView;// texture->GetImageView();
	normalTextureInfo.sampler = texture->GetSampler();

	vk::DescriptorImageInfo albedoTextureInfo{};
	albedoTextureInfo.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
	albedoTextureInfo.imageView = renderer->albedoImageView;// texture->GetImageView();
	albedoTextureInfo.sampler = texture->GetSampler();

	vk::DescriptorBufferInfo bufferInfo4{};
	bufferInfo4.buffer = buffers[3];
	bufferInfo4.offset = 0;
	bufferInfo4.range = sizeof(AmbientLight);

	vk::DescriptorBufferInfo bufferInfo5{};
	bufferInfo5.buffer = buffers[4];
	bufferInfo5.offset = 0;
	bufferInfo5.range = sizeof(DirectionalLight);




	std::array<vk::WriteDescriptorSet, 5> descriptorWrites{};

	descriptorWrites[0].setDstSet(lightdescriptorSet.get());
	descriptorWrites[0].setDstBinding(0);
	descriptorWrites[0].setDstArrayElement(0);
	descriptorWrites[0].setDescriptorType(vk::DescriptorType::eCombinedImageSampler);
	descriptorWrites[0].setDescriptorCount(1);
	descriptorWrites[0].setPImageInfo(&positionTextureInfo);

	descriptorWrites[1].setDstSet(lightdescriptorSet.get());
	descriptorWrites[1].setDstBinding(1);
	descriptorWrites[1].setDstArrayElement(0);
	descriptorWrites[1].setDescriptorType(vk::DescriptorType::eCombinedImageSampler);
	descriptorWrites[1].setDescriptorCount(1);
	descriptorWrites[1].setPImageInfo(&normalTextureInfo);

	descriptorWrites[2].setDstSet(lightdescriptorSet.get());
	descriptorWrites[2].setDstBinding(2);
	descriptorWrites[2].setDstArrayElement(0);
	descriptorWrites[2].setDescriptorType(vk::DescriptorType::eCombinedImageSampler);
	descriptorWrites[2].setDescriptorCount(1);
	descriptorWrites[2].setPImageInfo(&albedoTextureInfo);


	descriptorWrites[3].setDstSet(lightdescriptorSet.get());
	descriptorWrites[3].setDstBinding(3);
	descriptorWrites[3].setDstArrayElement(0);
	descriptorWrites[3].setDescriptorType(vk::DescriptorType::eUniformBuffer);
	descriptorWrites[3].setDescriptorCount(1);
	descriptorWrites[3].setPBufferInfo(&bufferInfo4);

	descriptorWrites[4].setDstSet(lightdescriptorSet.get());
	descriptorWrites[4].setDstBinding(4);
	descriptorWrites[4].setDstArrayElement(0);
	descriptorWrites[4].setDescriptorType(vk::DescriptorType::eUniformBuffer);
	descriptorWrites[4].setDescriptorCount(1);
	descriptorWrites[4].setPBufferInfo(&bufferInfo5);


	device.updateDescriptorSets(static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
}