当前位置: 首页 > article >正文

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

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 的实际类型是 CommandStream
    FEngine::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 id
        GLenum target = 0;
        GLenum internalFormat = 0;
        GLuint sidecarRenderBufferMS = 0;  // multi-sample sidecar renderbuffer

        // texture parameters go here too
        GLfloat 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.kler.cn/a/587750.html

相关文章:

  • C语言实现冒泡排序,超详解
  • Scheme语言的区块链
  • 【后端开发面试题】每日 3 题(十一)
  • Spring Boot实战:MySQL与Redis数据一致性深度解析与代码实战
  • 一.ffmpeg打开麦克风,录制音频并重采样
  • 地理信息系统(ArcGIS)在水文水资源及水环境中的应用:实践技术与案例分析深度剖析
  • 深入解析 TCP/IP 协议:架构、原理与应用
  • kmp报错→Cannot find skiko-windows-x64.dll.sha256
  • C++ 中的 RTTI(Run-Time Type Information,运行时类型识别)
  • 虚拟电商-数据库分库分表(二)
  • 16.使用读写包操作Excel文件:XlsxWriter 包
  • 中科院自动化所人形机器人研究进展:全面综述与展望
  • Git LFS (Large File Storage) 简介
  • Linux中Gdb调试工具常用指令大全
  • Vue.js 项目部署全解析:从开发到上线的关键旅程题
  • Elasticsearch集群与日志系统实战部署指南
  • JVM内存结构笔记03-方法区
  • Mysql查看执行计划、explain关键字详解(超详细)
  • linux在 Ubuntu 系统中设置服务器时间
  • WPF跨平台开发探讨:借助相关技术实现多平台应用