• 浅谈OpenGL之DSA


    今天准备写一篇文章简单介绍一下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);

  • 相关阅读:
    OTA JAR和JAD的mime不同
    document.getElementById('selCatalog').remove(i)突然无效???!
    判断WAP1.1和WAP2.0并解析为wml或xhtml
    IE和firefox下显示html内容
    unixrisk tip
    unixftp windows
    unixstdin/stdout/stderr
    峰鸟摄影
    linuxgrep commond
    unixtutorial(recommended)
  • 原文地址:https://www.cnblogs.com/hellobb/p/13943969.html
Copyright © 2020-2023  润新知