// // HitProxyPass:UE 式 GPU 拾取(像素级 id pass + 点击 readback)。 // // 两个 RG pass: // "HitProxy" —— 拾取请求帧把不透明 + 透明 batch 用 id 管线画进 // R32Uint 目标(片元值 = 实体位模式)。深度自测自写 // (重清主深度):遮挡语义 = 可见表面胜出;运行在 // Forward/ForwardTrans/PhysicsDebug 之后的 WAW 链尾, // 主链下游无人再读深度,下帧 Forward 照常重新 Clear // "HitProxyCopy" —— 请求像素 1×1 CopyImageToBuffer 进 host-visible // 暂存。TransferSrc use 让 RG 自动完成 // eColorAttachmentOptimal → eTransferSrcOptimal 迁移 // // 无请求帧零绘制零拷贝(barrier 照常插入,GPU 无实际工作)。 // 结果流:Renderer::TakePickResult(waitIdle 保证提交完成)→ 映射暂存。 // #ifndef HELLOVULKAN_HITPROXYPASS_H #define HELLOVULKAN_HITPROXYPASS_H #include #include #include #include #include namespace Engine { class Device; class ShaderManager; class DescriptorManager; namespace Passes { class SceneGpu; class HitProxyPass final : public RenderPass { public: HitProxyPass(Device& device, MemoryAllocator& allocator, ShaderManager& shaders, DescriptorManager& descriptors, SceneGpu& gpu, FrameSceneData& frame, RG::TextureHandle idTarget, RG::TextureHandle depth); ~HitProxyPass(); HitProxyPass(const HitProxyPass&) = delete; HitProxyPass& operator=(const HitProxyPass&) = delete; void Register(RG::RenderGraph& rg) override; // 有待取结果(拷贝已录制进当帧命令缓冲) bool HasPendingResult() const { return m_ResultValid; } // 取走拷贝结果(一次性)。调用方保证 GPU 已 idle //(Renderer::TakePickResult 内 waitIdle) bool TakeResult(u32& outBits); private: Device& m_Device; SceneGpu& m_Gpu; FrameSceneData& m_Frame; RG::TextureHandle m_IdTarget; RG::TextureHandle m_Depth; vk::PipelineLayout m_Layout; // Set0 = uboSetLayout,无 push vk::ShaderEXT m_Vert{}, m_Frag{}; // 1×1 像素暂存(host visible,持久映射);拷贝录制时置位 Scope m_Staging; bool m_ResultValid = false; }; } // namespace Passes } // namespace Engine #endif //HELLOVULKAN_HITPROXYPASS_H