Blender如何优雅的使用OpenGL之GPUBackend

在Blender中有多个引擎,其中Eevee引擎的特性是实时渲染性能好,这个系列的文章将以分析Eevee引擎的设计方法为目的,逐步探究Blender中为渲染工作所设计的各种类的作用。

GPUBackend类是一个充分包含渲染管线资源的虚类,先看一下它的定义。

namespace blender {
namespace gpu {

class Context;

class Batch;
class DrawList;
class Fence;
class FrameBuffer;
class IndexBuf;
class PixelBuffer;
class QueryPool;
class Shader;
class Texture;
class UniformBuf;
class StorageBuf;
class VertBuf;

class GPUBackend {
 public:
  virtual ~GPUBackend() = default;
  virtual void delete_resources() = 0;

  static GPUBackend *get();

  virtual void samplers_update() = 0;
  virtual void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) = 0;
  virtual void compute_dispatch_indirect(StorageBuf *indirect_buf) = 0;

  virtual Context *context_alloc(void *ghost_window, void *ghost_context) = 0;

  virtual Batch *batch_alloc() = 0;
  virtual DrawList *drawlist_alloc(int list_length) = 0;
  virtual Fence *fence_alloc() = 0;
  virtual FrameBuffer *framebuffer_alloc(const char *name) = 0;
  virtual IndexBuf *indexbuf_alloc() = 0;
  virtual PixelBuffer *pixelbuf_alloc(uint size) = 0;
  virtual QueryPool *querypool_alloc() = 0;
  virtual Shader *shader_alloc(const char *name) = 0;
  virtual Texture *texture_alloc(const char *name) = 0;
  virtual UniformBuf *uniformbuf_alloc(int size, const char *name) = 0;
  virtual StorageBuf *storagebuf_alloc(int size, GPUUsageType usage, const char *name) = 0;
  virtual VertBuf *vertbuf_alloc() = 0;

  /* Render Frame Coordination --
   * Used for performing per-frame actions globally */
  virtual void render_begin() = 0;
  virtual void render_end() = 0;
  virtual void render_step() = 0;
};

}  // namespace gpu
}  // namespace blender

在使用OpenGL时,Blender设计了一个子类GLBackend,用来实现OpenGL的实现方法;

namespace blender {
namespace gpu {

class GLBackend : public GPUBackend {
 private:
  GLSharedOrphanLists shared_orphan_list_;
#ifdef WITH_RENDERDOC
  renderdoc::api::Renderdoc renderdoc_;
#endif

 public:
  GLBackend()
  {
    /* platform_init needs to go first. */
    GLBackend::platform_init();

    GLBackend::capabilities_init();
    GLTexture::samplers_init();
  }
  ~GLBackend()
  {
    GLBackend::platform_exit();
  }

  void delete_resources() override
  {
    /* Delete any resources with context active. */
    GLTexture::samplers_free();
  }

  static GLBackend *get()
  {
    return static_cast<GLBackend *>(GPUBackend::get());
  }

  void samplers_update() override
  {
    GLTexture::samplers_update();
  };

  Context *context_alloc(void *ghost_window, void * /*ghost_context*/) override
  {
    return new GLContext(ghost_window, shared_orphan_list_);
  };

  Batch *batch_alloc() override
  {
    return new GLBatch();
  };

  DrawList *drawlist_alloc(int list_length) override
  {
    return new GLDrawList(list_length);
  };

  Fence *fence_alloc() override
  {
    return new GLFence();
  };

  FrameBuffer *framebuffer_alloc(const char *name) override
  {
    return new GLFrameBuffer(name);
  };

  IndexBuf *indexbuf_alloc() override
  {
    return new GLIndexBuf();
  };

  PixelBuffer *pixelbuf_alloc(uint size) override
  {
    return new GLPixelBuffer(size);
  };

  QueryPool *querypool_alloc() override
  {
    return new GLQueryPool();
  };

  Shader *shader_alloc(const char *name) override
  {
    return new GLShader(name);
  };

  Texture *texture_alloc(const char *name) override
  {
    return new GLTexture(name);
  };

  UniformBuf *uniformbuf_alloc(int size, const char *name) override
  {
    return new GLUniformBuf(size, name);
  };

  StorageBuf *storagebuf_alloc(int size, GPUUsageType usage, const char *name) override
  {
    return new GLStorageBuf(size, usage, name);
  };

  VertBuf *vertbuf_alloc() override
  {
    return new GLVertBuf();
  };

  GLSharedOrphanLists &shared_orphan_list_get()
  {
    return shared_orphan_list_;
  };

  void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) override
  {
    GLContext::get()->state_manager_active_get()->apply_state();
    GLCompute::dispatch(groups_x_len, groups_y_len, groups_z_len);
  }

  void compute_dispatch_indirect(StorageBuf *indirect_buf) override
  {
    GLContext::get()->state_manager_active_get()->apply_state();

    dynamic_cast<GLStorageBuf *>(indirect_buf)->bind_as(GL_DISPATCH_INDIRECT_BUFFER);
    /* This barrier needs to be here as it only work on the currently bound indirect buffer. */
    glMemoryBarrier(GL_COMMAND_BARRIER_BIT);

    glDispatchComputeIndirect((GLintptr)0);
    /* Unbind. */
    glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0);
  }

  /* Render Frame Coordination */
  void render_begin() override{};
  void render_end() override{};
  void render_step() override{};

  bool debug_capture_begin();
  void debug_capture_end();

 private:
  static void platform_init();
  static void platform_exit();

  static void capabilities_init();
};

}  // namespace gpu
}  // namespace blender

从GLBackend类的接口来看,可以确定GLShader等类也是继承自gup_shader_private.h文件中定的定义的Shader类,其他资源也是如此。由此可见,Blender使用了动态绑定的方法来管理渲染管线中的资源。

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值