OpenGL DSA(Direct State Access)

前言

直接状态访问( DSA ) 是一种修改 OpenGL 对象而无需将它们绑定到上下文的方法。这允许在本地上下文中修改对象状态,而不会影响应用程序所有部分共享的全局状态,即直接访问一个对象的状态而不需要绑定到全局状态机上。它还使 API 更加面向对象,因为可以清楚地识别修改对象状态的函数。

在 2014 年发布的 OpenGL4.5 标准,ARB_direct_state_access 扩展进入核心。在没有 DSA 的时代,需要按照状态机模式 bind 对象为当前操作对象后在进行全局操作。

文档:https://www.khronos.org/opengl/wiki/Direct_State_Access

文档:https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_direct_state_access.txt

正文

OpenGL 之前一直采用状态机模式进行操作,如顶点初始化数据:

glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

先调用 bind  绑定对象为状态机的全局对象,后面的操作虽然没有指定这个对象,但还是可以正确的对该对象进行操作。在代码复杂的时候,如果 bind 和操作没有匹配上就很尴尬了。频繁的切换 bind,驱动层频繁查找与解引用,影响性能。

在 2014 年发布的 OpenGL4.5 标准,ARB_direct_state_access 扩展进入核心。

一些接口命名上的更新:

 

这里有一些不同点。以前的 glGen* 系列函数只生成对象 id,内部没有初始化相关状态,这是在 glBind* 时进行的;而 4.5 的 DSA 提供的 glCreate* 系列函数,生成 id 的同时也进行了初始化。还有就是,很多 DSA 函数,都需要配合 glCreate* 来使用,不能用于 glGen* 。

对比

顶点不使用DSA:

glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

顶点使用DSA:

glCreateVertexArrays(1, &vao);
glCreateBuffers(1, &vbo);
glNamedBufferStorage(vbo, sizeof(vertices), vertices, GL_DYNAMIC_STORAGE_BIT);
glVertexArrayVertexBuffer(vao, 0, vbo, 0, 3*sizeof(float));
glEnableVertexArrayAttrib(vao, 0);
glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(vao, 0, 0);

以下来自参考博客

着色器程序不使用DSA:

glUseProgram(progId);
glUniform1f(loc, x);

着色器程序使用DSA:

glProgramUniform1fEXT(progId, loc, x);

纹理不使用 DSA:

glGenTextures(1, &name); 
glBindTexture(GL_TEXTURE_2D, name); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height); 
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

纹理使用 DSA:

glCreateTextures(GL_TEXTURE_2D, 1, &name);
glTextureParameteri(name, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTextureParameteri(name, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); 
glTextureParameteri(name, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteri(name, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTextureStorage2D(name, 1, GL_RGBA8, width, height); 
glTextureSubImage2D(name, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

帧缓冲不使用DSA:

glGenFramebuffers(1, &fbo); 
glBindFramebuffer(GL_FRAMEBUFFER, fbo); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tid, 0);

帧缓冲使用DSA:

glCreateFramebuffers(1, &fbo); 
glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, tex, 0); 
glNamedFramebufferTexture(fbo, GL_DEPTH_ATTACHMENT, depthTex, 0);

缓冲不使用DSA:

struct vertex_t { vec3 pos, nrm; vec2 tex; }; glBindVertexArray(vao); 
glBindVertexBuffer(0, vbo, 0, sizeof(vertex_t)); 
glEnableVertexAttribArray(0); 
glEnableVertexAttribArray(1); 
glEnableVertexAttribArray(2); 
glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, offsetof(vertex_t, pos)); 
glVertexAttribFormat(1, 3, GL_FLOAT, GL_FALSE, offsetof(vertex_t, nrm)); 
glVertexAttribFormat(2, 2, GL_FLOAT, GL_FALSE, offsetof(vertex_t, tex)); 
glVertexAttribBinding(0, 0); 
glVertexAttribBinding(1, 0); 
glVertexAttribBinding(2, 0);

缓冲使用DSA: 

glVertexArrayVertexBuffer(vao, 0, data->vbo, 0, sizeof(vertex_t)); 
glEnableVertexArrayAttrib(vao, 0); 
glEnableVertexArrayAttrib(vao, 1); 
glEnableVertexArrayAttrib(vao, 2); 
glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, offsetof(vertex_t, pos)); 
glVertexArrayAttribFormat(vao, 1, 3, GL_FLOAT, GL_FALSE, offsetof(vertex_t, nrm)); 
glVertexArrayAttribFormat(vao, 2, 2, GL_FLOAT, GL_FALSE, offsetof(vertex_t, tex)); 
glVertexArrayAttribBinding(vao, 0, 0); 
glVertexArrayAttribBinding(vao, 1, 0); 
glVertexArrayAttribBinding(vao, 2, 0);

参考

文档:https://www.khronos.org/opengl/wiki/Direct_State_Access

文档:https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_direct_state_access.txt

博客:https://zhuanlan.zhihu.com/p/23257409

博客:https://zhuanlan.zhihu.com/p/33504469

博客:https://blog.csdn.net/gggg_ggg/article/details/52701699

博客:https://www.cnblogs.com/hellobb/p/13943969.html

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龚建波

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值