OpenGl 4.5 DSA新特性

OpenGL4.5引入了DSA扩展,允许直接访问对象状态而无需绑定到全局状态机,降低了状态泄露风险并提高了程序效率。DSA通过新的API如glProgramUniform1fEXT、glTextureParameteri等简化了资源管理和操作,减少了状态切换次数,但在实际渲染时仍需绑定对象。DSA在减少状态机管理开销的同时,为渲染引擎设计提供了便利。
摘要由CSDN通过智能技术生成

转载来源:https://www.cnblogs.com/hellobb/p/13943969.html

今天准备写一篇文章简单介绍一下OpenGL4.5引入的一个新的扩展ARB_direct_state_access,这个扩展为OpenGL引入了一个新的特性就是Direct State Acess,下文统称为DSA。

那么什么是DSA,又为什么要引入DSA呢?

了解OpenGL的都知道,它的设计是一个基于状态机的API,你的每一次资源绑定,纹理绑定,修改渲染状态等等都会改变一个全局的状态机。这种设计的最大问题就是容易造成状态泄露,你可能只是想为纹理设置一个参数,但是却要改变状态机的纹理绑定,而这个状态你如果不修改,会一直泄露到其他的DrawCall中。这就给基于OpenGL的渲染引擎设计带来很多的问题,大多数引擎都会通过自己的方式来确保一个DrawCall的状态不会泄露到另一个DrawCall,从而导致一些非常难以调试的BUG。

那么为了从一定程度上缓解这个问题,OpenGL就引入了DSA。DSA可以让你直接访问一个object的状态而不需要绑定到全局状态机上 。比如没有DSA时,你需要先绑定一个buffer的object,才能为它分配存储空间,上传数据等,而有了DSA,你就可以直接访问object,为它分配存储,上传数据,避免将其绑定到状态机上。

但是我为什么说是一定程度上缓解呢,因为DSA不能完全避免绑定,当你将buffer或者texture真正用到渲染进程上时,你还是要将它们绑定到上下文里。比如前面你通过DSA的方式分配了一个buffer object,也为它上传了数据,现在你想将其用到某次DrawCall中作为uniform数据,你就需要调用glBindBufferRange(GL_UNIFORM_BUFFER,object,…)。将object绑定到指定Target上。

虽然如此,有了DSA还是可以为程序设计带来很多的方便。你仅仅需要在真正绘制的时候绑定object,而不是在各种初始化时就要绑定它,从一定程度上减少了状态机切换的次数。

下面我就简单列举几个DSA引入的新的API和旧的API之间的对比

//Program
//Without DSA:
glUseProgram(progId);
glUniform1f(loc, x);
//With DSA:
glProgramUniform1fEXT(progId, loc, x);
//Texture
/*Without 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);

 

// With 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);
// Framebuffer
Without DSA:
glGenFramebuffers(1, &fbo); 
glBindFramebuffer(GL_FRAMEBUFFER, fbo); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tid, 0);
 

// With DSA:
glCreateFramebuffers(1, &fbo); 
glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, tex, 0); 
glNamedFramebufferTexture(fbo, GL_DEPTH_ATTACHMENT, depthTex, 0);
 
Buffer
//Without 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);
 

// With 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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值