#pragma once #include #include #include #include #include #include #include #include class EngineContext; class RenderGraph { public: void init(EngineContext* ctx); void clear(); // Import externally owned images (swapchain, drawImage, g-buffers) RGImageHandle import_image(const RGImportedImageDesc& desc); // Create transient images (not used in v1 skeleton; stubbed for future) RGImageHandle create_image(const RGImageDesc& desc); // Convenience: create a transient depth image suitable for shadow mapping or depth-only passes // Format defaults to D32_SFLOAT; usage is depth attachment + sampled so it can be read later. RGImageHandle create_depth_image(const char* name, VkExtent2D extent, VkFormat format = VK_FORMAT_D32_SFLOAT); // Buffer import/create helpers RGBufferHandle import_buffer(const RGImportedBufferDesc& desc); RGBufferHandle create_buffer(const RGBufferDesc& desc); // Pass builder API struct Pass; // fwd using RecordCallback = std::function; using BuildCallback = std::function; void add_pass(const char* name, RGPassType type, BuildCallback build, RecordCallback record); // Legacy simple add void add_pass(const char* name, RGPassType type, RecordCallback record); // Build internal state for this frame (no-op in v1) bool compile(); // Execute in insertion order (skips disabled passes) void execute(VkCommandBuffer cmd); // Convenience import helpers (read from EngineContext::swapchain) RGImageHandle import_draw_image(); RGImageHandle import_depth_image(); RGImageHandle import_gbuffer_position(); RGImageHandle import_gbuffer_normal(); RGImageHandle import_gbuffer_albedo(); RGImageHandle import_swapchain_image(uint32_t index); void add_present_chain(RGImageHandle sourceDraw, RGImageHandle targetSwapchain, std::function appendExtra = {}); // --- Debug helpers --- struct RGDebugPassInfo { std::string name; RGPassType type{}; bool enabled = true; uint32_t imageReads = 0; uint32_t imageWrites = 0; uint32_t bufferReads = 0; uint32_t bufferWrites = 0; uint32_t colorAttachmentCount = 0; bool hasDepth = false; }; struct RGDebugImageInfo { uint32_t id{}; std::string name; bool imported = true; VkFormat format = VK_FORMAT_UNDEFINED; VkExtent2D extent{0,0}; VkImageUsageFlags creationUsage = 0; int firstUse = -1; int lastUse = -1; }; struct RGDebugBufferInfo { uint32_t id{}; std::string name; bool imported = true; VkDeviceSize size = 0; VkBufferUsageFlags usage = 0; int firstUse = -1; int lastUse = -1; }; size_t pass_count() const { return _passes.size(); } const char* pass_name(size_t i) const { return i < _passes.size() ? _passes[i].name.c_str() : ""; } bool pass_enabled(size_t i) const { return i < _passes.size() ? _passes[i].enabled : false; } void set_pass_enabled(size_t i, bool e) { if (i < _passes.size()) _passes[i].enabled = e; } void debug_get_passes(std::vector& out) const; void debug_get_images(std::vector& out) const; void debug_get_buffers(std::vector& out) const; private: struct ImportedImage { RGImportedImageDesc desc; RGImageHandle handle; }; struct Pass { std::string name; RGPassType type{}; RecordCallback record; // Declarations std::vector imageReads; std::vector imageWrites; std::vector bufferReads; std::vector bufferWrites; std::vector colorAttachments; bool hasDepth = false; RGAttachmentInfo depthAttachment{}; std::vector preImageBarriers; std::vector preBufferBarriers; // Cached rendering info derived from declared attachments (filled at execute) bool hasRendering = false; VkExtent2D renderExtent{}; bool enabled = true; }; EngineContext* _context = nullptr; RGResourceRegistry _resources; std::vector _passes; };