GLSL的“相干"精​​确度如何? GPU驱动程序解释的内存限定符用于多遍渲染? [英] How exactly is GLSL's "coherent" memory qualifier interpreted by GPU drivers for multi-pass rendering?

查看:112
本文介绍了GLSL的“相干"精​​确度如何? GPU驱动程序解释的内存限定符用于多遍渲染?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于一致的"内存限定符,GLSL规范指出:其中读写之间与其他着色器调用的读写一致的内存变量"..

The GLSL specification states, for the "coherent" memory qualifier: "memory variable where reads and writes are coherent with reads and writes from other shader invocations".

在实践中,我不确定现代GPU驱动程序如何针对多次渲染进行解释.当GLSL规范声明其他着色器调用"时,这是指仅在当前通过期间运行的着色器调用,还是过去或将来通过中的任何可能的着色器调用?出于我的目的,我将通过定义为"glBindFramebuffer-glViewPort-glUseProgram-glDrawABC-glDrawXYZ-glDraw123" 周期;我目前在每个渲染循环迭代"中执行2次这样的遍,但是以后每次迭代可能会有更多遍.

In practice, I'm unsure how this is interpreted by modern-day GPU drivers with regards to multiple rendering passes. When the GLSL spec states "other shader invocations", does that refer to shader invocations running only during the current pass, or any possible shader invocations in past or future passes? For my purposes, I define a pass as a "glBindFramebuffer-glViewPort-glUseProgram-glDrawABC-glDrawXYZ-glDraw123" cycle; where I'm currently executing 2 such passes per "render loop iteration" but may have more per iteration later on.

推荐答案

当GLSL规范声明其他着色器调用"时,这是指仅在当前通过期间运行的着色器调用,还是过去或将来通过的任何可能的着色器调用?

When the GLSL spec states "other shader invocations", does that refer to shader invocations running only during the current pass, or any possible shader invocations in past or future passes?

它的确切含义是:其他着色器调用".可能是相同的程序代码.可能是不同的代码.没关系:不是这个的着色器调用.

It means exactly what it says: "other shader invocations". It could be the same program code. It could be different code. It doesn't matter: shader invocations that aren't this one.

通常,OpenGL为您处理同步,因为OpenGL可以很容易地跟踪它.如果您映射一个缓冲区对象的范围,对其进行修改并取消映射,则OpenGL会知道您已经(可能)更改了多少东西.如果使用glTexSubImage2D,它将知道您进行了多少更改.如果您进行转换反馈,它可以确切知道将多少数据写入了缓冲区.

Normally, OpenGL handles synchronization for you, because OpenGL can track this fairly easily. If you map a range of a buffer object, modify it, and unmap it, OpenGL knows how much stuff you've (potentially) changed. If you use glTexSubImage2D, it knows how much stuff you changed. If you do transform feedback, it can know exactly how much data was written to the buffer.

如果确实将反馈转换为缓冲区,然后将其绑定为顶点数据的源,则OpenGL知道这将使管线停滞.它必须等到变换反馈完成后再清除一些缓存,才能将缓冲区用于顶点数据.

If you do transform feedback into a buffer, then bind it as a source for vertex data, OpenGL knows that this will stall the pipeline. That it must wait until the transform feedback has completed, and then clear some caches in order to use the buffer for vertex data.

在处理图像加载/存储时,您全部丢失了.由于可能以完全随机,未知和不可知的方式编写大量代码,因此OpenGL通常会在规则方面发挥作用,以使您能够灵活地获得最大的性能.这会触发很多未定义的行为.

When you're dealing with image load/store, you lose all of this. Because so much could be written in a completely random, unknown, and unknowable fashion, OpenGL generally plays really loose with the rules in order to allow you flexibility to get the maximum possible performance. This triggers a lot of undefined behavior.

通常,您可以遵循的唯一规则是OpenGL 4.2规范第2.11.13节中概述的规则.最大的一个(用于着色器与着色器的对话)是舞台上的规则.如果您是在片段着色器中,则可以安全地假设已经完成了专门计算您的三角形的点/线/三角形的顶点着色器.因此,您可以自由加载它们存储的值.但是,仅来自造您的人.

In general, the only rules you can follow are those outlined in section 2.11.13 of the OpenGL 4.2 specification. The biggest one (for shader-to-shader talk) is the rule on stages. If you're in a fragment shader, it is safe to assume that the vertex shader(s) that specifically computed the point/line/triangle for your triangle have completed. Therefore, you can freely load values that were stored by them. But only from the ones that made you.

您的着色器无法假设在先前的渲染命令中执行的着色器已经完成(鉴于刚才所说的,我知道这听起来很奇怪,但请记住:仅从创建您的对象开始").您的着色器无法假设在相同的渲染命令中使用相同的制服,图像,纹理等完成了对同一着色器的其他调用,除非适用上述条件.

Your shaders cannot make assumptions that shaders executed in previous rendering commands have completed (I know that sounds odd, given what was just said, but remember: "only from the ones that made you"). Your shaders cannot make assumptions that other invocations of the same shader, using the same uniforms, images, textures, etc, in the same rendering command have completed, except where the above applies.

您唯一可以假设的是,自己编写的着色器实例本身是可见的.因此,如果您执行imageStore并通过相同的变量对同一内存位置进行imageLoad,则可以保证返回相同的值.

The only thing you can assume is that writes your shader instance itself made are visible... to itself. So if you do an imageStore and do an imageLoad to the same memory location through the same variable, then you are guaranteed to get the same value back.

好吧,除非同时有人给它写信.

Well, unless someone else wrote to it in the meantime.

您的着色器不能假设以后的渲染命令肯定会肯定获取前一个写入的值(通过图像存储或原子更新). 以后再多!无论您绑定到上下文什么都没有关系.上载或下载的内容无关紧要(从技术上讲.很可能您在某些情况下会获得正确的行为,但是未定义的行为仍然是 undefined ).

Your shaders cannot assume that a later rendering command will certainly fetch values written (via image store or atomic updates) by a previous one. No matter how much later! It doesn't matter what you've bound to the context. It doesn't matter what you've uploaded or downloaded (technically. Odds are you'll get correct behavior in some cases, but undefined behavior is still undefined).

如果需要保证,如果需要发出将获取由图像存储/原子更新写入的值的渲染命令,则必须在发出写入调用之后和发出读取调用之前的某个时间显式要求同步内存.这是通过 glMemoryBarrier 完成的.

If you need that guarantee, if you need to issue a rendering command that will fetch values written by image store/atomic updates, you must explicitly ask synchronize memory sometime after issuing the writing call and before issuing the reading call. This is done with glMemoryBarrier.

因此,如果渲染要进行图像存储的对象,则不能渲染要使用已存储数据的对象,直到已发送适当的屏障(显式在着色器中或显式在OpenGL代码中).这可能是图像加载操作.但是它可能是从着色器代码编写的缓冲区对象渲染的.可能是纹理获取.它可能正在与附加到FBO的图像进行融合.没关系你做不到.

Therefore, if you render something that does image storing, you cannot render something that uses the stored data until an appropriate barrier has been sent (either explicitly in the shader or explicitly in OpenGL code). This could be an image load operation. But it could be rendering from a buffer object written by shader code. It could be a texture fetch. It could be doing blending to an image attached to the FBO. It doesn't matter; you can't do it.

请注意,这适用于处理所有图像加载/存储/原子操作的 all 操作,而不仅仅是着色器操作.因此,如果您使用图像存储来写入图像,则除非使用GL_TEXTURE_UPDATE_BARRIER_BIT​屏障,否则不一定会读取正确的数据.

Note that this applies for all operations that deal with image load/store/atomic, not just shader operations. So if you use image store to write to an image, you won't necessarily read the right data unless you use a GL_TEXTURE_UPDATE_BARRIER_BIT​ barrier.

这篇关于GLSL的“相干"精​​确度如何? GPU驱动程序解释的内存限定符用于多遍渲染?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆