首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >生锈模拟各种豆荚系列化

生锈模拟各种豆荚系列化
EN

Stack Overflow用户
提问于 2022-08-17 07:54:40
回答 2查看 57关注 0票数 0

在C++中,我有以下模板:

代码语言:javascript
复制
template<typename UBO>
std::pair<uint, std::vector<std::byte>> SerializeUniform(UBO& ubo, uint binding)
{
    // Create raw binary buffers of the uniform data
    std::vector<std::byte> ubo_buffer(sizeof(UBO));
    memcpy(ubo_buffer.data(), (void*)&ubo, sizeof(UBO));
    return {binding, ubo_buffer};
}

inline void SerializeArguments(NECore::UniformBufferDataContainer& data) {}

template<typename T1, typename... Ts>
inline void SerializeArguments(
    NECore::UniformBufferDataContainer& data, T1& uniform, uint binding, Ts&... args)
{
    data.push_back(SerializeUniform(uniform, binding));
    SerializeArguments(data, args...);
}

template<class... Ubos>
void ModuleStorage::Draw(const NECore::RenderRequest& render_request, const Ubos&... args)
{
    size_t arg_num = _details::ArgNum(args...);
    NECore::UniformBufferDataContainer ubos;
    ubos.reserve(arg_num);
    _details::SerializeArguments(ubos, args...);

    if(render_request.image_outputs.empty())
        DrawToScreen(vk_meta_data.vulkan_data, render_request, ubos);
    else
       DrawOffScreen(vk_meta_data.vulkan_data, render_request, ubos);
}

读起来有点难,所以让我带你去看看。

第一个模板接受POD并将其数据复制到一个字节向量中,然后创建一个元组将数据与整数关联起来。

下一个模板是递归模板的基本情况,没有参数,什么也不做。

接下来,我们有一个递归模板,接受前两个参数,假设为POD和整数,并序列化POD。回溯到尾巴上。

也就是说,这个模板允许我序列化任意数量的荚。

最后,我有一个多样化的模板,允许我序列化任意数量的豆荚。

你可能想知道为什么要经历这么多麻烦。这样我才能写出这样的东西:

代码语言:javascript
复制
    modules.Draw(
        {
            gltf_shader,
            {gallery.GetGpuMeshData(model_names[selected_model])},
            textures,
            ssbos
        },
        mvp, 0,
        gltf_info, 1);

通过这种方式,render命令可以接受任意数量的统一参数,这意味着我可以使用相同的模式和语法,用我想要的任何输入(只要它们是与着色器声明兼容的字节)调用任意的任意着色器。

我正在移植这个库来生锈,我想用宏实现类似的目标。也就是说,我想要清楚地定义我可以调用的东西

代码语言:javascript
复制
draw(render_request, macro!(ubo1, 0, ubo2, 1))

或者更好(但我几乎可以肯定,这不可能是生锈的)

代码语言:javascript
复制
draw(render_request, ubo1, 0, ubo2, 1)

我很难想出这个宏。主要问题是,宏不是函数,铁锈不支持各种参数。我不太清楚如何定义宏来实现我想要的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-17 09:41:57

我从标准库中侵入了vec!宏,从而成功地使它工作起来。

代码语言:javascript
复制
macro_rules! UBO {
    () => {Vec::<UniformBufferData>::new()};
    ($($ubo:expr, $binding : expr),* $(,)?) =>
    {
        [$(serialize_uniform(&$ubo, $binding)),+].to_vec()
    }
}

这允许您调用宏UBO!(dummy2, 0, dummy, 1, dummy3, 3)

它扩展到

代码语言:javascript
复制
[
    serialize_uniform(&dummy2, 0),
    serialize_uniform(&dummy, 1),
    serialize_uniform(&dummy3, 3),
]
.to_vec()

所以现在你可以做:

代码语言:javascript
复制
draw(render_request, UBO!(var1, 0, var2, 2, var3, 7));

而且它应该能起作用(UB和其他的恶作剧除外)。

票数 0
EN

Stack Overflow用户

发布于 2022-08-17 08:27:46

通常的方法是定义一个函数,它接受实现一个特征的泛型类型,并为X元素的元组实现这个特征(用一个宏)。

例如:

代码语言:javascript
复制
pub trait Arguments {
    fn serialize(self, ubo: &mut UniformBufferDataContainer);
}

macro_rules! impl_arguments {
    (
        ( $first_generic:ident $($rest_generics:ident)* )
        ( $first_binding:ident $($rest_bindings:ident)* )
    ) => {
        // Impl for tuples with N elements.
        impl_arguments_impl!( ( $first_generic $($rest_generics)* ) ( $first_binding $($rest_bindings)* ) );
        // Recurse to impl for tuples with N - 1 and less elements.
        impl_arguments!( ( $($rest_generics)* ) ( $($rest_bindings)* ) );
    };

    // Recursion end condition.
    ( ( ) ( ) ) => {};
}
macro_rules! impl_arguments_impl {
    ( ( $($generics:ident)+ ) ( $($bindings:ident)+ ) ) => {
        impl<$($generics,)+> Arguments for ( $( &'_ $generics, u32, )+ ) {
            fn serialize(self, ubo: &mut UniformBufferDataContainer) {
                // Destructure the tuple to access individual arguments.
                #[allow(non_snake_case)]
                let ( $( $generics, $bindings, )+ ) = self;
                $(
                    ubo.push_back(serialize_uniform($generics, $bindings));
                )+
            }
        }
    };
}

impl_arguments!((H G F E D C B A) (binding8 binding7 binding6 binding5 binding4 binding3 binding2 binding1));

pub fn draw<Ubos: Arguments>(render_request: &mut RenderRequest, args: Ubos) {
    // ...
    args.serialize(&mut ubos);
    // ...
}

然后你把它叫做:

代码语言:javascript
复制
draw(render_request, (&a, 0, &b, 1));
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73384755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档