From 77749eff876209c33ba9236c8b7fb1503af5cbb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Sun, 30 Oct 2022 14:56:54 +0100 Subject: DRW: Manager: Add possibility to record a framebuffer change inside a pass This is a convenience when one needs to often change the current framebuffer and avoid the overhead of creating many Main/Simple passes. --- source/blender/draw/intern/draw_command.cc | 10 ++++++++++ source/blender/draw/intern/draw_command.hh | 8 ++++++++ source/blender/draw/intern/draw_pass.hh | 14 ++++++++++++-- source/blender/gpu/GPU_framebuffer.h | 3 +++ source/blender/gpu/intern/gpu_framebuffer.cc | 5 +++++ source/blender/gpu/intern/gpu_framebuffer_private.hh | 5 +++++ 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/source/blender/draw/intern/draw_command.cc b/source/blender/draw/intern/draw_command.cc index 882eda9b31d..10dd63e05dc 100644 --- a/source/blender/draw/intern/draw_command.cc +++ b/source/blender/draw/intern/draw_command.cc @@ -30,6 +30,11 @@ void ShaderBind::execute(RecordingState &state) const } } +void FramebufferBind::execute() const +{ + GPU_framebuffer_bind(framebuffer); +} + void ResourceBind::execute() const { if (slot == -1) { @@ -229,6 +234,11 @@ std::string ShaderBind::serialize() const return std::string(".shader_bind(") + GPU_shader_get_name(shader) + ")"; } +std::string FramebufferBind::serialize() const +{ + return std::string(".framebuffer_bind(") + GPU_framebuffer_get_name(framebuffer) + ")"; +} + std::string ResourceBind::serialize() const { switch (type) { diff --git a/source/blender/draw/intern/draw_command.hh b/source/blender/draw/intern/draw_command.hh index 145ec0fe231..ab180cc60b1 100644 --- a/source/blender/draw/intern/draw_command.hh +++ b/source/blender/draw/intern/draw_command.hh @@ -88,6 +88,7 @@ enum class Type : uint8_t { DispatchIndirect, Draw, DrawIndirect, + FramebufferBind, PushConstant, ResourceBind, ShaderBind, @@ -118,6 +119,13 @@ struct ShaderBind { std::string serialize() const; }; +struct FramebufferBind { + GPUFrameBuffer *framebuffer; + + void execute() const; + std::string serialize() const; +}; + struct ResourceBind { eGPUSamplerState sampler; int slot; diff --git a/source/blender/draw/intern/draw_pass.hh b/source/blender/draw/intern/draw_pass.hh index 24dfdd1b97b..892dfdddfcf 100644 --- a/source/blender/draw/intern/draw_pass.hh +++ b/source/blender/draw/intern/draw_pass.hh @@ -14,8 +14,7 @@ * #Pass. Use many #PassSub along with a main #Pass to reduce the overhead and allow groupings of * commands. \note The draw call order inside a batch of multiple draw with the exact same state is * not guaranteed and is not even deterministic. Use a #PassSimple or #PassSortable if ordering is - * needed. \note As of now, it is also quite limited in the type of draw command it can record - * (no custom vertex count, no custom first vertex). + * needed. Custom vertex count and custom first vertex will effectively disable batching. * * `PassSimple`: * Does not have the overhead of #PassMain but does not have the culling and batching optimization. @@ -191,6 +190,12 @@ class PassBase { */ void shader_set(GPUShader *shader); + /** + * Bind a framebuffer. This is equivalent to a deferred GPU_framebuffer_bind() call. + * \note Changes the global GPU state (outside of DRW). + */ + void framebuffer_set(GPUFrameBuffer *framebuffer); + /** * Bind a material shader along with its associated resources. Any following bind() or * push_constant() call will use its interface. @@ -743,6 +748,11 @@ template inline void PassBase::shader_set(GPUShader *shader) create_command(Type::ShaderBind).shader_bind = {shader}; } +template inline void PassBase::framebuffer_set(GPUFrameBuffer *framebuffer) +{ + create_command(Type::FramebufferBind).framebuffer_bind = {framebuffer}; +} + template inline void PassBase::material_set(Manager &manager, GPUMaterial *material) { GPUPass *gpupass = GPU_material_get_pass(material); diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index bdb384c16f1..917407eece3 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -47,6 +47,9 @@ typedef struct GPUOffScreen GPUOffScreen; GPUFrameBuffer *GPU_framebuffer_create(const char *name); void GPU_framebuffer_free(GPUFrameBuffer *fb); void GPU_framebuffer_bind(GPUFrameBuffer *fb); + +const char *GPU_framebuffer_get_name(GPUFrameBuffer *fb); + /** * Workaround for binding a SRGB frame-buffer without doing the SRGB transform. */ diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index 6528f39d4ec..5b50fd66196 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -238,6 +238,11 @@ void GPU_framebuffer_free(GPUFrameBuffer *gpu_fb) delete unwrap(gpu_fb); } +const char *GPU_framebuffer_get_name(GPUFrameBuffer *gpu_fb) +{ + return unwrap(gpu_fb)->name_get(); +} + /* ---------- Binding ----------- */ void GPU_framebuffer_bind(GPUFrameBuffer *gpu_fb) diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh index 5afcc102e44..cb7fd62445c 100644 --- a/source/blender/gpu/intern/gpu_framebuffer_private.hh +++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh @@ -204,6 +204,11 @@ class FrameBuffer { { return attachments_[GPU_FB_COLOR_ATTACHMENT0 + slot].tex; }; + + inline const char *const name_get() const + { + return name_; + }; }; /* Syntactic sugar. */ -- cgit v1.2.3