Google Filament 渲染引擎(2)-Backend 核心类介绍

embedded/2025/3/13 11:00:10/

Google Filament 渲染引擎(2)-Backend 核心类介绍

请添加图片描述

阅读说明:

  • 本文基于 filament 版本: v1.58.0
  • 文本更加阐述 Backend 内部核心类的关系, 示例代码作了非常多的删减和简化

文本将以创建纹理为例, 阐述 Backend 内部的流程。后端图形接口以 OpenGL 为例。

核心类的功能概览:

  • Dispatcher: 本质上只是一个函数指针的集合,用于将命令与驱动接口的方法绑定。在初始化阶段,这些函数指针就被填充好。
  • Driver: 负责管理底层驱动的状态,以及与硬件交互的具体实现。
  • CommandStream: 负责接收命令,并将其发送到驱动。
  • Command: 命令对象,包含了具体的命令类型和参数, 负责命令的封装和执行.
  • Engine: 负责管理资源的创建和销毁,以及命令的提交。

一、底层驱动初始化

// --------------------------------- step1: 创建 Driver ----------------------------------
Backend mBackend = Backend::OPENGL;
// 根据类型选择平台, 以 PlatformCocoaGL 为例
PlatformCocoaGL platform = filament::backend::PlatformFactory::create(&mBackend);// 根据平台创建驱动, 这里 driver 的类型是 OpenGLDriver
Driver* driver = platform->createDriver();// --------------------------------- step2: 创建 CommandStream ----------------------------------
using DriverApi = filament::backend::CommandStream;
// 这里完成 底层驱动 绑定到 CommandStream 的 Dispatcher 上
DriverApi* driverApi = new DriverApi(*driver);

二、创建纹理

应用层创建代码:

filament::Texture* texture = Texture::Builder().levels(1).sampler(Texture::Sampler::SAMPLER_EXTERNAL).build(*mEngine);
Texture* Texture::Builder::build(Engine& engine) {// 调用 Engine 的 createTexture 方法return downcast(engine).createTexture(*this);
}

三、核心类

1、Engine
// ====> 模板展开后的 createTexture 函数
FTexture* FEngine::createTexture(const Texture::Builder& builder) noexcept {// 展开 create 模板调用FTexture* p = mHeapAllocator.make<FTexture>(*this, builder);if (p) {mTextures.insert(p);}return p;
}
FTexture::FTexture() {backend::Handle<backend::HwTexture> mHandle;// driver 的实际类型是 CommandStreamFEngine::DriverApi& driver = engine.getDriverApi();mHandle = driver.createTexture(mTarget, mLevelCount, mFormat, mSampleCount, mWidth, mHeight, mDepth, mUsage);
}
2、CommandStream
// 构造函数:
CommandStream::CommandStream(Driver& driver, CircularBuffer& buffer) noexcept: mDriver(driver),mCurrentBuffer(buffer),mDispatcher(driver.getDispatcher())
{}
// 纹理创建函数inline backend::TextureHandle createTexture(backend::SamplerType target,uint8_t levels,backend::TextureFormat format,uint8_t samples,uint32_t width,uint32_t height,uint32_t depth,backend::TextureUsage usage) {// 分配结构体内存backend::TextureHandle result = this->mDriver.createTextureS();// 定义命令类型using Cmd = CommandType<decltype(&Driver::createTextureR)>::Command<&Driver::createTextureR>;// 分配命令缓冲区内存void* const p = this->allocateCommand(CommandBase::align(sizeof(Cmd)));// 在分配的内存上构造命令对象new (p) Cmd(// 真正需要执行的命令this->mDispatcher.createTexture_,backend::TextureHandle(result),std::move(target),std::move(levels),std::move(format),std::move(samples),std::move(width),std::move(height),std::move(depth),std::move(usage));return result;}
3、Command
// 特化模板类 Command
template<>
class Command<&filament::backend::Driver::createTextureR> : public filament::backend::CommandBase {using SavedParameters = std::tuple<std::remove_reference_t<filament::backend::Handle<filament::backend::HwTexture>>,std::remove_reference_t<filament::backend::SamplerType>,std::remove_reference_t<unsigned char>,std::remove_reference_t<filament::backend::TextureFormat>,std::remove_reference_t<unsigned char>,std::remove_reference_t<unsigned int>,std::remove_reference_t<unsigned int>,std::remove_reference_t<unsigned int>,std::remove_reference_t<filament::backend::TextureUsage>>;SavedParameters mArgs;void log() noexcept;template <std::size_t ...I>void log(std::index_sequence<I...>) noexcept;public:template <typename M, typename D>static inline void execute(M &&method, D &&driver, filament::backend::CommandBase *base, intptr_t *next);inline Command(Command<&filament::backend::Driver::createTextureR> &&rhs) noexcept = default;template <typename ...A>inline constexpr explicit Command(filament::backend::Execute execute, A &&...args);template<>inline constexpr explicit Command<filament::backend::Handle<filament::backend::HwTexture>,filament::backend::SamplerType,unsigned char,filament::backend::TextureFormat,unsigned char,unsigned int,unsigned int,unsigned int,filament::backend::TextureUsage>(filament::backend::Execute execute,filament::backend::Handle<filament::backend::HwTexture> &&arg1,filament::backend::SamplerType &&arg2,unsigned char &&arg3,filament::backend::TextureFormat &&arg4,unsigned char &&arg5,unsigned int &&arg6,unsigned int &&arg7,unsigned int &&arg8,filament::backend::TextureUsage &&arg9) : filament::backend::CommandBase(execute),mArgs(std::forward<filament::backend::Handle<filament::backend::HwTexture>>(arg1),std::forward<filament::backend::SamplerType>(arg2),std::forward<unsigned char>(arg3),std::forward<filament::backend::TextureFormat>(arg4),std::forward<unsigned char>(arg5),std::forward<unsigned int>(arg6),std::forward<unsigned int>(arg7),std::forward<unsigned int>(arg8),std::forward<filament::backend::TextureUsage>(arg9)) {}static inline void *operator new(std::size_t, void *ptr) {if (__builtin_expect(!(ptr), false)) {utils::panic(__func__, "root/filament/filament/backend/include/private/backend/CommandStream.h", 159, "ptr");}return ptr;}
};
4、Driver
1)命令的绑定
Dispatcher OpenGLDriver::getDispatcher() const noexcept {auto dispatcher = ConcreteDispatcher<OpenGLDriver>::make();return dispatcher;
}
2)分配结构体内存
struct GLTexture : public HwTexture {using HwTexture::HwTexture;struct GL {GL() noexcept : imported(false), external(false), sidecarSamples(1), reserved1(0) {}GLuint id = 0;          // texture or renderbuffer idGLenum target = 0;GLenum internalFormat = 0;GLuint sidecarRenderBufferMS = 0;  // multi-sample sidecar renderbuffer// texture parameters go here tooGLfloat anisotropy = 1.0;int8_t baseLevel = 127;int8_t maxLevel = -1;uint8_t reserved0 = 0;bool imported           : 1;bool external           : 1;uint8_t sidecarSamples  : 3;uint8_t reserved1       : 3;std::array<TextureSwizzle, 4> swizzle{TextureSwizzle::CHANNEL_0,TextureSwizzle::CHANNEL_1,TextureSwizzle::CHANNEL_2,TextureSwizzle::CHANNEL_3};} gl;mutable Handle<GLTextureRef> ref;OpenGLPlatform::ExternalTexture* externalTexture = nullptr;
};// 分配内存并构造一个 filament::backend::GLTexture 对象
template<> Handle<GLTexture> initHandle<filament::backend::GLTexture, <>>() {return this->mHandleAllocator.allocateAndConstruct<filament::backend::GLTexture>();
}Handle<HwTexture> OpenGLDriver::createTextureS() noexcept {return this->initHandle<GLTexture>();
}
3)使用 OpenGL API 创建纹理
void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8_t levels,TextureFormat format, uint8_t samples, uint32_t w, uint32_t h, uint32_t depth,TextureUsage usage) {auto &gl = this->mContext;glTexStorage2D(t->gl.target, GLsizei(t->levels), t->gl.internalFormat, GLsizei(width), GLsizei(height));// ...
}
5、Dispatcher
using Execute = void (*)(Driver& driver, CommandBase* self, intptr_t* next);
Execute createTexture_;
// 这里完成 底层驱动 绑定到 Dispatcher 上
template <typename ConcreteDriver> class ConcreteDispatcher {static void createTexture(Driver &driver, CommandBase *base, intptr_t *next) {using Cmd = CommandType<decltype(&Driver::createTextureR)>::Command<&Driver::createTextureR>;ConcreteDriver &concreteDriver = static_cast<ConcreteDriver &>(driver);Cmd::execute(& ConcreteDriver::createTextureR, concreteDriver, base, next);}
}
template <typename ConcreteDriver> Dispatcher ConcreteDispatcher<ConcreteDriver>::make() {Dispatcher dispatcher;dispatcher.createTexture_ = &ConcreteDispatcher<T>::createTexture;// ...return dispatcher;
}

四、总结

这表明 Engine -> CommandStream -> Dispatcher 形成了调用链,每一层都负责不同的任务,Engine 负责 API 层接口,CommandStream 负责命令封装,Dispatcher 负责命令派发, Driver 负责最终执行。

五、辅助工具

1)Engine

命令出处:

cmake-build-debug/compile_commands.json

预处理命令:

// root/filament:
clang++ -E \
-I../libs/filabridge/include \
-I../third_party/robin-map \
-I../libs/utils/include \
-I../libs/filaflat/include \
-I../libs/math/include \
-I../cmake-build-debug/filament/ \
-I./include \
-I./backend/include \
-I./src/details \
-I./components \
-I./src \
./src/details/Engine.cpp -o 123.cpp

编译模板展开:

// root/filament:
clang++ \
-Xclang -ast-print -fsyntax-only -std=c++17 \root/filament/filament/src/Engine.cpp > record_layouts.txt 2>&1 \
-Iroot/filament/filament/include \
-Iroot/filament/cmake-build-debug/filament \
-Iroot/filament/filament/src \
-Iroot/filament/filament/backend/include \
-Iroot/filament/libs/math/include \
-Iroot/filament/libs/utils/include \
-Iroot/filament/third_party/robin-map/tnt/.. \
-Iroot/filament/libs/bluevk/include \
-Iroot/filament/third_party/vkmemalloc/tnt/../include \
-Iroot/filament/third_party/smol-v/tnt/../source \
-Iroot/filament/libs/filaflat/include \
-Iroot/filament/libs/filabridge/include \
-Iroot/filament/libs/ibl/include \
-Iroot/filament/libs/matdbg/include \
-Iroot/filament/third_party/civetweb/tnt/../include \
-Iroot/filament/libs/filamat/include \
-Iroot/filament/cmake-build-debug/shaders \
-Iroot/filament/cmake-build-debug/include \
-Iroot/filament/third_party/glslang/glslang/tnt/../Include \
-Iroot/filament/third_party/glslang/glslang/tnt/../Public \
-Iroot/filament/third_party/glslang/glslang/tnt/../MachineIndependent \
-Iroot/filament/third_party/glslang/glslang/tnt/../.. \
-Iroot/filament/third_party/glslang/SPIRV/tnt/.. \
-Iroot/filament/third_party/glslang/SPIRV/tnt/../.. \
-Iroot/filament/third_party/spirv-tools/include \
-Iroot/filament/third_party/spirv-headers/include \
-Iroot/filament/third_party/spirv-cross/tnt/..
2)CommandStream

预处理命令:

// root/filament/backend:
g++ -E -I../../libs/utils/include -I../../libs/math/include -I../include -I./include  ./src/CommandStream.cpp -o CommandStream.i
3)Driver
clang++ \
-Xclang -ast-print -fsyntax-only -std=c++17 \
root/filament/backend/src/opengl/OpenGLDriver.cpp > record_layouts.txt 2>&1 \
-Iroot/filament/include \
-Iroot/cmake-build-debug/filament \
-Iroot/filament/src \
-Iroot/filament/backend/include \
-Iroot/filament/backend/src \
-Iroot/cmake-build-debug/filament/backend \
-Iroot/libs/math/include \
-Iroot/libs/utils/include \
-Iroot/third_party/robin-map/tnt/.. \
-Iroot/libs/bluegl/include \
-Iroot/libs/bluevk/include \
-Iroot/third_party/vkmemalloc/tnt/../include \
-Iroot/third_party/smol-v/tnt/../source \
-Iroot/third_party/spirv-headers/include

http://www.ppmy.cn/embedded/172220.html

相关文章

TikTok多店铺网络安全搭建指南

在跨境电商和社交电商的浪潮中&#xff0c;TikTok已成为许多商家拓展业务的重要平台。随着多店铺运营模式的普及&#xff0c;网络安全问题也日益凸显。如何搭建一个安全、稳定的网络环境&#xff0c;保障多店铺数据的安全性和业务的连续性&#xff0c;成为商家亟需解决的问题。…

Python----计算机视觉处理(opencv:像素,RGB颜色,图像的存储,opencv安装,代码展示)

一、计算机眼中的图像 像素 像素是图像的基本单元&#xff0c;每个像素存储着图像的颜色、亮度和其他特征。一系列像素组合到一起就形成 了完整的图像&#xff0c;在计算机中&#xff0c;图像以像素的形式存在并采用二进制格式进行存储。根据图像的颜色不 同&#xff0c;每个像…

vue的 props 与 $emit 以及 provide 与 inject 的 组件之间的传值对比

好的&#xff0c;下面是 props 与 $emit 以及 provide 与 inject 的对比&#xff1a; 1. props 与 $emit props&#xff1a;父组件通过 props 向子组件传递数据&#xff0c;子组件接收后不可修改。子组件只能读取 props 传递给它的数据。如果需要修改或更新父组件的状态&#…

设计模式在 JDK 中的具体应用与分析

一、设计模式 GOF 设计模式是面向对象设计中常见问题的可复用解决方案&#xff0c;通过 23 种经典模式 提供了一套标准化的设计思路&#xff0c;用于解决软件设计中反复出现的架构和交互问题。其核心特点包括&#xff1a; 经验驱动&#xff1a;源于实际项目的经验总结&#xf…

目录《Vue 3 + TypeScript + DeepSeek 全栈开发实战》

在快速迭代的软件开发世界里&#xff0c;技术的融合与创新始终是推动行业前行的不竭动力。今天&#xff0c;我们站在了前端技术与大数据搜索技术交汇的十字路口&#xff0c;手中的工具不再仅仅是编码的利器&#xff0c;更是解锁未来应用无限可能的钥匙。正是基于这样的时代背景…

【踩坑记录】MAC M4 mini 系统初始化

① 一定要准备好一个usb拓展坞&#xff0c;否则连不上键鼠&#xff01; ② 初始化时&#xff0c;跳过mac账号登录&#xff0c;进入系统后再登录快一百倍&#xff01; ③ 安装nvm&#xff0c;遇到报错&#xff1a;xcode-select: note: install requested for command line dev…

从信息一体到智能联动:辉视智慧学校广播系统全面提升校园管理效率

在智慧校园的建设中&#xff0c;高效、安全的沟通系统是保障教学秩序和校园安全的重要基石。辉视智慧学校广播对讲解决方案&#xff0c;以先进的IP网络和SIP协议为核心&#xff0c;不仅继承了传统广播系统的全部功能&#xff0c;更在此基础上进行了全面革新&#xff0c;为师生打…

Java 8 Stream 面试题

一、问题 Java 8 中的 Stream 用过吗&#xff1f;请介绍一下。 二、回答 1.概述 Stream 是 Java 8 中提供的对数据集合进行处理和运算的一套 API&#xff0c;能够非常方便地对数据集合进行处理。 Stream 的意思就是流&#xff0c;对于 Stream 的处理可以这样理解&#xff0c…