考虑典型的“天真”顶点着色器:
in vec3 aPos;
uniform mat4 uMatCam;
uniform mat4 uMatModelView;
uniform mat4 uMatProj;
void main () {
gl_Position = uMatProj * uMatCam * uMatModelView * vec4(aPos, 1.0);
}
Run Code Online (Sandbox Code Playgroud)
当然,传统观点会建议“每个顶点乘以三个 mat4,其中两个即使在当前着色器程序中的多个后续 glDrawX() 调用中也是一致的,至少这两个应该在 CPU 端预乘,可能甚至所有三个。”
我想知道现代 GPU 是否已将此用例优化到 CPU 端预乘不再具有性能优势的程度。当然,纯粹主义者可能会说“这取决于最终用户的 OpenGL 实现”,但对于这个用例,我们可以安全地假设它将是提供该实现的当前一代支持 OpenGL 4.2 的 nVidia 或 ATI 驱动程序。
根据您的经验,考虑到我们可能会在每次 UseProgram() 传递中“绘制”一百万个左右的顶点——每个 UseProgram() 将至少预乘前两个(透视投影和相机变换矩阵)将性能提升到任何显着程度?每个 Draw() 调用的所有三个怎么样?
当然,这完全是关于基准测试......但我希望有人拥有基本的、基于当前硬件实现的见解我错过了这可能表明“甚至不值得一试,不要浪费你的时间”或“一定要这样做,因为您当前没有预乘法的着色器将是纯粹的疯狂” ......想法?
我有一个调用glDrawArrays的OpenGL渲染代码,当OpenGL上下文(自动/隐式获取)时,它可以完美地运行4.2但是在显式请求的OpenGL核心上下文3.2中一致地失败(GL_INVALID_OPERATION).(在两种情况下,着色器始终设置为#version 150,但这与我怀疑的点不同.)
根据规范,glDrawArrays()在GL_INVALID_OPERATION失败时只有两个实例:
"如果非零缓冲区对象名称绑定到已启用的数组,并且缓冲区对象的数据存储当前已映射" - 此时我没有进行任何缓冲区映射
"如果几何着色器处于活动状态且模式与[...]不兼容" - nope,则截至目前没有几何着色器.
此外:
我已经验证并仔细检查了它只是glDrawArrays()调用失败了.还要仔细检查传递给glDrawArrays()的所有参数在GL版本,缓冲区绑定下是否相同.
这发生在3个不同的nvidia GPU和2个不同的操作系统(Win7和OSX,都是64位 - 当然,在OSX中我们只有 3.2上下文,无论如何都不是4.2).
使用集成的"Intel HD"GPU不会发生这种情况,但对于那个,我只获得一个自动的隐式3.3上下文(试图通过GLFW明确强制使用此GPU的3.2核心配置文件在这里无法创建窗口,但这是一个完全不同的问题...)
对于它的价值,这里是在Golang中从渲染循环中摘录的相关例程:
func (me *TMesh) render () {
curMesh = me
curTechnique.OnRenderMesh()
gl.BindBuffer(gl.ARRAY_BUFFER, me.glVertBuf)
if me.glElemBuf > 0 {
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, me.glElemBuf)
gl.VertexAttribPointer(curProg.AttrLocs["aPos"], 3, gl.FLOAT, gl.FALSE, 0, gl.Pointer(nil))
gl.DrawElements(me.glMode, me.glNumIndices, gl.UNSIGNED_INT, gl.Pointer(nil))
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
} else {
gl.VertexAttribPointer(curProg.AttrLocs["aPos"], 3, gl.FLOAT, gl.FALSE, 0, gl.Pointer(nil))
/* BOOM! */
gl.DrawArrays(me.glMode, 0, me.glNumVerts)
}
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
}
Run Code Online (Sandbox Code Playgroud)
所以当然这是更大的渲染循环的一部分,尽管现在整个"*TMesh"构造只是两个实例,一个是简单的立方体,另一个是简单的金字塔.重要的是整个绘图循环完美无缺,在3.3和4.2下查询GL时没有报告错误,但是3个具有显式3.2核心配置文件的nvidia GPU失败并且错误代码根据规范只调用了两个具体情况,据我所知,这里没有一个适用.
这可能有什么问题?你碰到过这个吗?我缺少什么想法?
现在,这是一种非常奇怪的行为。
TL;DR——在渲染到纹理设置中,在调整窗口(帧缓冲区 0)大小时,只有下一次调用glClear(GL_COLOR_BUFFER_BIT)绑定帧缓冲区 0(窗口的客户区)会给出GL_OUT_OF_MEMORY,仅在两个中的一个GPU,但是渲染仍然正确且正确地进行。
现在,所有重要的细节:
所以这是在带有两个 GPU 的 Vaio Z 上(可以通过机器上的物理切换按钮切换到):
OpenGL 4.2.0 @ NVIDIA Corporation GeForce GT 640M LE/PCIe/SSE2(GLSL:4.20 NVIDIA 通过 Cg 编译器)
OpenGL 4.0.0 - Build 9.17.10.2867 @ Intel Intel(R) HD Graphics 4000 (GLSL: 4.00 - Build 9.17.10.2867)
我的程序在使用 GLFW 64 位的 Win 7 64 位下的 Go 1.0.3 64 位。
我有一个相当简单直接的渲染到纹理“迷你管道”。首先,普通 3D 几何体使用最简单的着色器(没有照明,什么都没有,只有纹理三角形网格,它们只是一些立方体和平面)渲染到具有深度/模板渲染缓冲区作为深度/模板附件和texture2D 作为颜色附件。对于纹理,所有过滤都被禁用,mip-maps 也是如此。
然后我渲染一个全屏四边形(实际上是一个“超大”全屏三边形),只是从带有 texelFetch(tex, gl_FragCoord.xy, 0) 的所述帧缓冲区纹理(颜色附件)中采样,因此不使用包装。
两个 GPU 都可以很好地呈现这一点,无论是在我强制执行核心配置文件还是不执行核心配置文件时。没有为此报告任何 GL 错误,所有渲染也按预期进行。除非我在使用 Intel HD 4000 GPU 的 GL 4.0 渲染器(在 Core …
这是我正在编写的特定于域的文件IO函数的摘录:
let
cp :: FilePath -> IO ()
cp "." = putStr "" -- OUCH!
cp ".." = putStr "" -- CRIKEY!
cp fname = custom logic here...
in mapM_ cp filepaths
Run Code Online (Sandbox Code Playgroud)
我理解mapM_让我们放弃/忽略所有IO ()结果,所以我想要一个更清洁的替代品putStr ""---即.Haskell的"规范"方式来编写"一个不做任何事情的类型正确的无操作IO(或monad)表达式".
从我的新手阅读中我undefined想到了,虽然这个编译并没有引起任何问题,但它会产生一个不需要的stdout打印main.hs: Prelude.undefined(我在这里stack runghc main.hs用作唯一的编码环境---它就足够了,但上面的代码将以递归的方式循环通过目录树:这将是(重新)了解更好,或更确切地说"正确"方式的好时机.
GLSL规范规定,对于"相干"内存限定符:"内存变量,其中读取和写入与来自其他着色器调用的读取和写入一致".
实际上,我不确定现代GPU驱动程序如何解释多个渲染过程.当GLSL规范声明"其他着色器调用"时,它是指仅在当前传递期间运行的着色器调用,还是过去或将来传递中的任何可能的着色器调用?为了我的目的,我将一个传递定义为"glBindFramebuffer-glViewPort-glUseProgram-glDrawABC-glDrawXYZ-glDraw123"循环; 我现在正在每次"渲染循环迭代"执行2次这样的传递,但是稍后可能会有更多的每次迭代.
考虑以下GLSL函数:
float Pow3 (const in float f) {
return f * f * f;
}
float Pow4 (const in float f) {
return f * f * f * f;
}
float Pow5 (const in float f) {
return f * f * f * f * f;
}
Run Code Online (Sandbox Code Playgroud)
... 等等.有没有一种方法,以#定义一个宏GLSL可以产生ñ乘法-OF- ˚F逐本身在编译的时候,不使用内置GLSL POW()当然功能?
现在我有这个小帮手:
both f (one,two) = (f one , f two)
Run Code Online (Sandbox Code Playgroud)
然后我无所事事地想知道是否fmap"迭代"一个元组,所以我问GHCi:
fmap reverse ("aA","bB")
Run Code Online (Sandbox Code Playgroud)
结果是:
("aA","Bb")
Run Code Online (Sandbox Code Playgroud)
奇!因此,fmap对元组的语义似乎是"将func应用于snd",如果你愿意的话.
有什么内容base或Prelude我应该使用而不是我自己的both?Hoogle 没有给出有希望的结果,或者我错误地解析了它们.
片段着色器使用两个原子计数器.它可能会或可能不会增加第一个,可能会或可能不会增加第二个(但从不两者).但是,在修改计数器之前,总会读取它们的当前值,如果计数器稍后被修改,那些先前读取的值将用于某些自定义逻辑.所有这些都发生在(很可能是不可滚动的)循环中.
设想一个大致如下的流程:
问题:着色器查询当前计数器值 - 它是否始终获得"最新"值?我是否在这里失去了碎片着色器的大规模并行性(仅就当代和未来的GPU和驱动程序而言)?
至于分支(如果x) -我比较另一纹素(readonly restrict uniform)uimage1D的(uniform)uint.因此,一个操作数肯定是一个统一的标量,但另一个是一个imageLoad().x虽然图像是统一的 - 这种分支仍然是"完全并行化"的吗?你可以看到两个分支都是两个,几乎相同的指令.假设一个"完美优化"的GLSL编译器,这种分支是否会引入停顿?
我正在使用以下简单的Go代码来分配大小为1024x1024x1024的3D数组:
grid = make([][][]TColor, 1024)
for x = 0; x < 1024; x++ {
grid[x] = make([][]TColor, 1024)
for y = 0; y < 1024; y++ {
grid[x][y] = make([]TColor, 1024)
}
}
Run Code Online (Sandbox Code Playgroud)
TColor结构是一个4分量的float64向量:
type TColor struct { R, G, B, A float64 }
Run Code Online (Sandbox Code Playgroud)
通过分配中途(x = 477和y = ~600ish),最内层的make()调用恐慌... 运行时:内存不足:无法分配65536字节块(17179869184正在使用中)
这可以在较低的网格分辨率下工作,即256³,128³等.现在由于结构的大小是4x4字节,整个网格应该只需要16 GB的内存.我的机器(openSuse 12.1 64bit)具有32 GB的可寻址物理(即非虚拟)内存.为什么Go(weekly.2012-02-22)甚至不能分配一半呢?
只是一个随机的思考,看着我的无数次length调用,我发现编译器可以通过不变性和引用透明度来判断任何列表的长度(即使新的列表concat来自现有的已知列表/代码路径).那么它可能会在低级代码生成期间的某个阶段length l用实际的 int常量替换所有"调用" ,对吗?
想知道它是否确实存在,或者我是否在初学者中缺少关于纯函数式语言/编译器的东西.
使用encoding/xml.Decoder我试图手动解析从http://www.khronos.org/files/collada_schema_1_4加载的XML文件
出于测试目的,我只是迭代文档打印出遇到的任何令牌类型:
func Test (r io.Reader) {
var t xml.Token
var pa *xml.Attr
var a xml.Attr
var co xml.Comment
var cd xml.CharData
var se xml.StartElement
var pi xml.ProcInst
var ee xml.EndElement
var is bool
var xd = xml.NewDecoder(r)
for i := 0; i < 24; i++ {
if t, err = xd.Token(); (err == nil) && (t != nil) {
if a, is = t.(xml.Attr); is { print("ATTR\t"); println(a.Name.Local) }
if pa, is = t.(*xml.Attr); is { print("*ATTR\t"); …Run Code Online (Sandbox Code Playgroud)