#pragma once #include "renderer_api/renderer_api.h" #include #include namespace pp::renderer { enum class RecordedRenderCommandKind : std::uint8_t { begin_render_pass, set_viewport, bind_shader, bind_texture, bind_mesh, draw, upload_texture, read_texture, capture_frame, blit_render_target, end_render_pass, trace_marker, }; struct RecordedRenderCommand { RecordedRenderCommandKind kind = RecordedRenderCommandKind::draw; TextureDesc target_desc {}; ClearColor clear_color {}; Viewport viewport {}; MeshDesc mesh_desc {}; TextureDesc texture_desc {}; std::uint32_t texture_slot = 0; TextureDesc source_desc {}; TextureDesc destination_desc {}; ReadbackRegion readback_region {}; ReadbackRegion source_region {}; ReadbackRegion destination_region {}; BlitFilter blit_filter = BlitFilter::nearest; std::uint64_t upload_bytes = 0; std::uint64_t readback_bytes = 0; std::uint64_t capture_bytes = 0; std::uint64_t blit_source_bytes = 0; std::uint64_t blit_destination_bytes = 0; const char* component = ""; const char* name = ""; }; class RecordingTexture2D final : public ITexture2D { public: explicit RecordingTexture2D(TextureDesc desc) noexcept; [[nodiscard]] TextureDesc desc() const noexcept override; private: TextureDesc desc_ {}; }; class RecordingRenderTarget final : public IRenderTarget { public: explicit RecordingRenderTarget(TextureDesc color_desc) noexcept; [[nodiscard]] TextureDesc color_desc() const noexcept override; private: TextureDesc color_desc_ {}; }; class RecordingShaderProgram final : public IShaderProgram { public: explicit RecordingShaderProgram(const char* debug_name) noexcept; [[nodiscard]] const char* debug_name() const noexcept override; private: const char* debug_name_ = ""; }; class RecordingMesh final : public IMesh { public: explicit RecordingMesh(MeshDesc desc) noexcept; [[nodiscard]] MeshDesc desc() const noexcept override; private: MeshDesc desc_ {}; }; class RecordingReadbackBuffer final : public IReadbackBuffer { public: explicit RecordingReadbackBuffer(std::uint64_t size_bytes) noexcept; [[nodiscard]] std::uint64_t size_bytes() const noexcept override; private: std::uint64_t size_bytes_ = 0; }; class RecordingCommandContext final : public ICommandContext { public: explicit RecordingCommandContext(std::vector& commands) noexcept; [[nodiscard]] pp::foundation::Status begin_render_pass( IRenderTarget& target, ClearColor clear_color) noexcept override; [[nodiscard]] pp::foundation::Status set_viewport(Viewport viewport) noexcept override; [[nodiscard]] pp::foundation::Status bind_shader(IShaderProgram& shader) noexcept override; [[nodiscard]] pp::foundation::Status bind_texture( std::uint32_t slot, ITexture2D& texture) noexcept override; [[nodiscard]] pp::foundation::Status bind_mesh(IMesh& mesh) noexcept override; [[nodiscard]] pp::foundation::Status draw() noexcept override; [[nodiscard]] pp::foundation::Status read_texture( ITexture2D& texture, ReadbackRegion region, IReadbackBuffer& destination) noexcept override; [[nodiscard]] pp::foundation::Status upload_texture( ITexture2D& texture, ReadbackRegion region, std::span rgba_or_channel_bytes) noexcept override; [[nodiscard]] pp::foundation::Status capture_frame( IRenderTarget& target, IReadbackBuffer& destination) noexcept override; [[nodiscard]] pp::foundation::Status blit_render_target( IRenderTarget& source, ReadbackRegion source_region, IRenderTarget& destination, ReadbackRegion destination_region, BlitFilter filter) noexcept override; void end_render_pass() noexcept override; [[nodiscard]] bool in_render_pass() const noexcept; private: std::vector* commands_ = nullptr; TextureDesc active_target_ {}; bool in_render_pass_ = false; bool shader_bound_ = false; bool mesh_bound_ = false; }; class RecordingRenderTrace final : public IRenderTrace { public: explicit RecordingRenderTrace(std::vector& commands) noexcept; void marker(const char* component, const char* name) noexcept override; private: std::vector* commands_ = nullptr; }; class RecordingRenderDevice final : public IRenderDevice { public: RecordingRenderDevice() noexcept; [[nodiscard]] const char* backend_name() const noexcept override; [[nodiscard]] ICommandContext& immediate_context() noexcept override; [[nodiscard]] IRenderTrace* trace() noexcept override; [[nodiscard]] std::span commands() const noexcept; void clear() noexcept; private: std::vector commands_; RecordingCommandContext context_; RecordingRenderTrace trace_; }; [[nodiscard]] const char* recorded_render_command_kind_name(RecordedRenderCommandKind kind) noexcept; }