c++ - 如何让C++编译器知道一个函数是 `Idempotent`

标签 c++ opengl

我正在编写一个 OpenGL C++ 包装器。该包装器旨在减少复杂且易出错的用法。

例如,我目前希望用户只关注一点点 OpenGL Context。为此,我编写了一个类 gl_texture_2d。众所周知,一个OpenGL纹理基本上有以下操作:

  1. 设置u/v参数为repeat/mirror
  2. min/mag filter设置为linear
  3. ...

基于此,我们有:

class gl_texture_2d 
{
public:
  void mirror_u(); // set u parameter as mirror model
  void mirror_v(); // set v parameter as mirror model
  void linear_min_filter(); // ...
  void linear_mag_filter(); // ...
};

好吧,我们知道,只有当 OpenGL 纹理对象的句柄 当前绑定(bind)到 OpenGL 上下文 时,我们才能执行这些操作。 假设我们有一个函数这样做: 无效绑定(bind)(GLuint htex);//实际上是相关 GL 函数的别名

好的,我们现在可以将我们的 gl_texture_2d 用法设计为:

gl_texture_2d tex;
bind(tex.handle());
tex.mirror_u();
tex.linear_min_filter();
unbind(tex.handle());

它证实了 GL 的逻辑,但它失去了 wrapper 的意义,对吧?作为用户,我希望这样操作:

gl_texture_2d tex;
tex.mirror_u();
tex.linear_min_filter();

要实现这一点,我们必须实现类似以下功能:

void gl_texture_2d::mirror_u()
{
  glBindTexture(GL_TEXTURE_2D, handle());
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
  glBindTexture(GL_TEXTURE_2D, 0);
}

始终在内部进行绑定(bind)操作可确保操作有效。但成本昂贵!

代码:

tex.mirror_u();
tex.mirror_v();

会展开成一对无意义的绑定(bind)/解绑操作。

那么有没有什么机制可以让编译器知道:

  1. 如果 bind(b) 紧跟在 bind(a) 之后,则可以删除 bind(a)
  2. 如果 bind(a) 在一个 block 中出现两次,最后一次无效。

最佳答案

如果您正在使用 pre-DSA OpenGL ,并且您绝对必须使用您自己的 API 直接包装 OpenGL 调用,然后用户可能必须了解整个绑定(bind)到编辑的事情。毕竟,如果他们出于渲染目的绑定(bind)了一个纹理,然后他们尝试修改一个纹理,这可能会损坏当前的绑定(bind)。

因此,您应该将绑定(bind)到编辑的概念直接构建到 API 中。

也就是说,纹理对象(顺便说一句,它应该仅限于二维纹理)实际上不应该有修改它的函数,因为你不能在不绑定(bind)它的情况下修改 OpenGL 纹理(或者没有你真正应该学习的 DSA)。它不应该有 mirror_u 等等;这些函数应该是 Binder 对象的一部分:

bound_texture bind(some_texture, tex_unit);
bind.mirror_u();
...

bound_texture 的构造函数将 some_texture 绑定(bind)到 tex_unit。它的成员函数将修改该纹理(注意:它们需要调用 glActiveTexture 以确保没有人更改事件纹理单元)。

bound_texture 的析构函数应该自动解除绑定(bind)纹理。但是你应该有一个 release 成员函数来手动解除绑定(bind)。

关于c++ - 如何让C++编译器知道一个函数是 `Idempotent`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41287151/

相关文章:

C++ 在模板类上继承运算符 '<<'

c++ - C++中map []和map.at之间的区别?

c++ - 相同功能的不同实现(c/c++)

c++ - 将参数包解压到 std::initializer_list 中?

c++ - 成员类实例化

opengl - Rust、OpenGL - 距离在代码中相等,但在绘制后不相等

c++ - 将 SDL、SFML 或 GLFW 挂接到现有的 OpenGL 应用程序中

c++ - OpenGL glBegin ... glEnd

opengl - 如何在 OpenGL/LWJGL 中标准化鼠标坐标

opengl - 在桌面上为 OpenGL ES 开发