I seem to be running into issues with transitioning image layouts between subpasses. The three duplicate errors seem to suggest the position, normal and albedo attachments are the issue. I did read something about the use of input attachments being used in this sort of situation. Could these be used to address the issue or is their some other solution?

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.");
    }
}

Errors:

VUID-VkDescriptorImageInfo-imageLayout-00344(ERROR / SPEC): msgNum: -564812795 - Validation Error: [ VUID-VkDescriptorImageInfo-imageLayout-00344 ] Object 0: handle = 0x29f30e771e0, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0xde55a405 | vkCmdDraw: Cannot use VkImage 0xdd3a8a0000000015[] (layer=0 mip=0) with specific layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL that doesn't match the previous known layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. The Vulkan spec states: imageLayout must match the actual VkImageLayout of each subresource accessible from imageView at the time this descriptor is accessed as defined by the image layout matching rules (https://vulkan.lunarg.com/doc/view/1.3.239.0/windows/1.3-extensions/vkspec.html#VUID-VkDescriptorImageInfo-imageLayout-00344)
    Objects: 1
        [0] 0x29f30e771e0, type: 6, name: NULL
VUID-vkCmdDraw-None-02699(ERROR / SPEC): msgNum: 369680064 - Validation Error: [ VUID-vkCmdDraw-None-02699 ] Object 0: handle = 0x2a7f70000000053, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; | MessageID = 0x1608dec0 | vkCmdDraw: Descriptor set VkDescriptorSet 0x2a7f70000000053[] Image layout specified at vkCmdBindDescriptorSets time doesn't match actual image layout at time descriptor is used. See previous error callback for specific details. The Vulkan spec states: Descriptors in each bound descriptor set, specified via vkCmdBindDescriptorSets, must be valid as described by descriptor validity if they are statically used by the VkPipeline bound to the pipeline bind point used by this command (https://vulkan.lunarg.com/doc/view/1.3.239.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdDraw-None-02699)
    Objects: 1
        [0] 0x2a7f70000000053, type: 23, name: NULL
VUID-VkDescriptorImageInfo-imageLayout-00344(ERROR / SPEC): msgNum: -564812795 - Validation Error: [ VUID-VkDescriptorImageInfo-imageLayout-00344 ] Object 0: handle = 0x29f30e771e0, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0xde55a405 | vkCmdDraw: Cannot use VkImage 0xd10d270000000018[] (layer=0 mip=0) with specific layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL that doesn't match the previous known layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. The Vulkan spec states: imageLayout must match the actual VkImageLayout of each subresource accessible from imageView at the time this descriptor is accessed as defined by the image layout matching rules (https://vulkan.lunarg.com/doc/view/1.3.239.0/windows/1.3-extensions/vkspec.html#VUID-VkDescriptorImageInfo-imageLayout-00344)
    Objects: 1
        [0] 0x29f30e771e0, type: 6, name: NULL
VUID-vkCmdDraw-None-02699(ERROR / SPEC): msgNum: 369680064 - Validation Error: [ VUID-vkCmdDraw-None-02699 ] Object 0: handle = 0x2a7f70000000053, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; | MessageID = 0x1608dec0 | vkCmdDraw: Descriptor set VkDescriptorSet 0x2a7f70000000053[] Image layout specified at vkCmdBindDescriptorSets time doesn't match actual image layout at time descriptor is used. See previous error callback for specific details. The Vulkan spec states: Descriptors in each bound descriptor set, specified via vkCmdBindDescriptorSets, must be valid as described by descriptor validity if they are statically used by the VkPipeline bound to the pipeline bind point used by this command (https://vulkan.lunarg.com/doc/view/1.3.239.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdDraw-None-02699)
    Objects: 1
        [0] 0x2a7f70000000053, type: 23, name: NULL
VUID-VkDescriptorImageInfo-imageLayout-00344(ERROR / SPEC): msgNum: -564812795 - Validation Error: [ VUID-VkDescriptorImageInfo-imageLayout-00344 ] Object 0: handle = 0x29f30e771e0, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0xde55a405 | vkCmdDraw: Cannot use VkImage 0xcb1c7c000000001b[] (layer=0 mip=0) with specific layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL that doesn't match the previous known layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL. The Vulkan spec states: imageLayout must match the actual VkImageLayout of each subresource accessible from imageView at the time this descriptor is accessed as defined by the image layout matching rules (https://vulkan.lunarg.com/doc/view/1.3.239.0/windows/1.3-extensions/vkspec.html#VUID-VkDescriptorImageInfo-imageLayout-00344)
    Objects: 1
        [0] 0x29f30e771e0, type: 6, name: NULL
VUID-vkCmdDraw-None-02699(ERROR / SPEC): msgNum: 369680064 - Validation Error: [ VUID-vkCmdDraw-None-02699 ] Object 0: handle = 0x2a7f70000000053, type = VK_OBJECT_TYPE_DESCRIPTOR_SET; | MessageID = 0x1608dec0 | vkCmdDraw: Descriptor set VkDescriptorSet 0x2a7f70000000053[] Image layout specified at vkCmdBindDescriptorSets time doesn't match actual image layout at time descriptor is used. See previous error callback for specific details. The Vulkan spec states: Descriptors in each bound descriptor set, specified via vkCmdBindDescriptorSets, must be valid as described by descriptor validity if they are statically used by the VkPipeline bound to the pipeline bind point used by this command (https://vulkan.lunarg.com/doc/view/1.3.239.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdDraw-None-02699)
    Objects: 1
        [0] 0x2a7f70000000053, type: 23, name: NULL