#pragma once #include #include #include #include #include #include #include #include namespace mln { namespace gfx { class Renderable; } // namespace gfx namespace webgpu { class Context; class RenderPass; class UploadPass; class CommandEncoder final : public gfx::CommandEncoder { public: explicit CommandEncoder(Context& context_); ~CommandEncoder() override; webgpu::Context& getContext() { return context; } const webgpu::Context& getContext() const { return context; } WGPUCommandEncoder getEncoder() const { return encoder; } std::unique_ptr createUploadPass(const char* name, gfx::Renderable&) override; std::unique_ptr createRenderPass(const char* name, const gfx::RenderPassDescriptor&) override; void present(gfx::Renderable&) override; // WebGPU-specific: submit command buffer directly void submitCommandBuffer(); template void visitDebugGroups(TFunc f) { for (const auto& item : debugGroupNames) { f(item.name); } } private: friend class RenderPass; friend class UploadPass; // Track a RenderPass, propagating debug groups to it void trackRenderPass(RenderPass*); // Stop tracking a RenderPass void forgetRenderPass(RenderPass*); // Track an UploadPass, propagating debug groups to it void trackUploadPass(UploadPass*); // Stop tracking a RenderPass void forgetUploadPass(UploadPass*); void pushDebugGroup(const char* name) override; void popDebugGroup() override; protected: struct GroupEntry { std::string name; std::size_t renderGroups; std::size_t uploadGroups; }; protected: webgpu::Context& context; WGPUCommandEncoder encoder = nullptr; std::vector debugGroupNames; std::vector> renderDebugGroups; std::vector> uploadDebugGroups; mln::unordered_set renderPasses; mln::unordered_set uploadPasses; UploadPass* currentUploadPass = nullptr; }; } // namespace webgpu } // namespace mln