小编met*_*eap的帖子

是否应该在 CPU 上预乘(顶点着色器、mat4)统一矩阵?

考虑典型的“天真”顶点着色器:

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() 调用的所有三个怎么样?

当然,这完全是关于基准测试......但我希望有人拥有基本的、基于当前硬件实现的见解我错过了这可能表明“甚至不值得一试,不要浪费你的时间”“一定要这样做,因为您当前没有预乘法的着色器将是纯粹的疯狂” ......想法?

glsl matrix vertex-shader

5
推荐指数
1
解决办法
1010
查看次数

为什么OpenGL的glDrawArrays()在Core Profile 3.2下使用GL_INVALID_OPERATION失败,而不是3.3或4.2?

我有一个调用glDrawArrays的OpenGL渲染代码,当OpenGL上下文(自动/隐式获取)时,它可以完美地运行4.2但是在显式请求的OpenGL核心上下文3.2中一致地失败(GL_INVALID_OPERATION).(在两种情况下,着色器始终设置为#version 150,但这与我怀疑的点不同.)

根据规范,glDrawArrays()在GL_INVALID_OPERATION失败时只有两个实例:

  • "如果非零缓冲区对象名称绑定到已启用的数组,并且缓冲区对象的数据存储当前已映射" - 此时我没有进行任何缓冲区映射

  • "如果几何着色器处于活动状态且模式与[...]不兼容" - nope,则截至目前没有几何着色器.

此外:

  1. 我已经验证并仔细检查了它只是glDrawArrays()调用失败了.还要仔细检查传递给glDrawArrays()的所有参数在GL版本,缓冲区绑定下是否相同.

  2. 这发生在3个不同的nvidia GPU和2个不同的操作系统(Win7和OSX,都是64位 - 当然,在OSX中我们只有 3.2上下文,无论如何都不是4.2).

  3. 使用集成的"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失败并且错误代码根据规范只调用了两个具体情况,据我所知,这里没有一个适用.

这可能有什么问题?你碰到过这个吗?我缺少什么想法?

opengl go vertex-buffer vertex-array opengl-3

5
推荐指数
1
解决办法
4294
查看次数

glClear() 在 Intel HD 4000 (GL 4.0) 上提供 GL_OUT_OF_MEMORY 而不是 GeForce (GL 4.2) ......为什么?

现在,这是一种非常奇怪的行为。

TL;DR——在渲染到纹理设置中,在调整窗口(帧缓冲区 0)大小时,只有下一次调用glClear(GL_COLOR_BUFFER_BIT)绑定帧缓冲区 0(窗口的客户区)会给出GL_OUT_OF_MEMORY,仅在两个中的一个GPU,但是渲染仍然正确且正确地进行。

现在,所有重要的细节:

所以这是在带有两个 GPU 的 Vaio Z 上(可以通过机器上的物理切换按钮切换到):

  1. OpenGL 4.2.0 @ NVIDIA Corporation GeForce GT 640M LE/PCIe/SSE2(GLSL:4.20 NVIDIA 通过 Cg 编译器)

  2. 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 …

opengl framebuffer go render-to-texture

5
推荐指数
1
解决办法
2186
查看次数

如何在Haskell中构造一个no-op IO()表达式?

这是我正在编写的特定于域的文件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用作唯一的编码环境---它就足够了,上面的代码将以递归的方式循环通过目录树:这将是(重新)了解更好,或更确切地说"正确"方式的好时机.

monads haskell io-monad

5
推荐指数
1
解决办法
575
查看次数

GLRE的"连贯"内存限定符究竟是由GPU驱动程序解释为多遍渲染?

GLSL规范规定,对于"相干"内存限定符:"内存变量,其中读取和写入与来自其他着色器调用的读取和写入一致".

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

opengl textures glsl multipass

4
推荐指数
1
解决办法
3688
查看次数

GLSL宏扩展能做到这一点吗?

考虑以下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()当然功能?

opengl macros shader glsl fragment-shader

4
推荐指数
1
解决办法
8118
查看次数

对元组的所有值进行任何内置的fmap-of-sort?

现在我有这个小帮手:

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",如果你愿意的话.

有什么内容basePrelude我应该使用而不是我自己的both?Hoogle 没有给出有希望的结果,或者我错误地解析了它们.

haskell

3
推荐指数
1
解决办法
123
查看次数

片段着色器中的GLSL原子计数器(和分支)

片段着色器使用两个原子计数器.它可能会或可能不会增加第一个,可能会或可能不会增加第二个(但从不两者).但是,在修改计数器之前,总会读取它们的当前值,如果计数器稍后被修改,那些先前读取的值将用于某些自定义逻辑.所有这些都发生在(很可能是不可滚动的)循环中.

设想一个大致如下的流程:

  • 在一些小的不可滚动的循环中,比如FOR 0-20(编译时可解析的const)...
  • 获取AC1和AC2的计数器值
  • 检查一些价值:
  • 如果x:在索引AC1的uimage1D_A中设置texel,则递增AC1
  • else:在索引(imgwidth-AC2-1)的uimage1D_B中设置texel,增加AC2

问题:着色器查询当前计数器值 - 它是否始终获得"最新"值?我是否在这里失去了碎片着色器的大规模并行性(仅就当代和未来的GPU和驱动程序而言)?

至于分支(如果x) -我比较另一纹素(readonly restrict uniform)uimage1D的(uniform)uint.因此,一个操作数肯定是一个统一的标量,但另一个是一个imageLoad().x虽然图像是统一的 - 这种分支仍然是"完全并行化"的吗?你可以看到两个分支都是两个,几乎相同的指令.假设一个"完美优化"的GLSL编译器,这种分支是否会引入停顿?

opengl parallel-processing gpgpu glsl fragment-shader

1
推荐指数
1
解决办法
1661
查看次数

如何在Go中分配16GB的内存?

我正在使用以下简单的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)甚至不能分配一半呢?

ram memory-management large-data-volumes go

1
推荐指数
2
解决办法
903
查看次数

GHC将"长度"调用重写为常量整数吗?

只是一个随机的思考,看着我的无数次length调用,我发现编译器可以通过不变性和引用透明度来判断任何列表的长度(即使新的列表concat来自现有的已知列表/代码路径).那么它可能会在低级代码生成期间的某个阶段length l实际的 int常量替换所有"调用" ,对吗?

想知道它是否确实存在,或者我是否在初学者中缺少关于纯函数式语言/编译器的东西.

haskell ghc

1
推荐指数
1
解决办法
108
查看次数

为什么Go的encoding/xml.Decoder.Token()不会产生xml.Attr标记呢?

使用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)

xml xsd xml-attribute go xml-parsing

0
推荐指数
1
解决办法
2084
查看次数