影响程序输出的 3D 纹理大小不会抛出错误

3D texture size affecting program output without error being thrown

首先,我使用 glDebugMessage() 而不是 glGetError() 来确定错误。

其次,我分配一个3D纹理存储如下:

glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, 512, 512, 303, 0, GL_RGBA, GL_FLOAT, NULL);

当深度分量为 303 或更小时,我的程序完全按预期工作(我在纹理中分配了一种颜色,我看到该颜色作为输出),当该参数为 304 或更高时,程序不会工作(黑屏)。

我在不同的机器上测试了相同的程序,并且根据计算机的不同,阈值会发生变化,有时会更高,有时会更低。

我的假设是某些驱动程序无法分配足够的内存来处理此纹理。但是没有抛出任何错误,或者至少没有调用调试消息。

有没有一种方法可以验证我确实请求了比分配的内存更多的内存并以某种方式扩展所述内存?

是的,如果我计算正确的话,303 纹理是 ~1.2GByte。然而,您的 gfx 卡也需要用于帧缓冲区和其他内容的内存。遗憾的是,没有通用的 GL API 来查询可用内存。但是,有一些扩展。这就是我在 OpenGL 引擎中查询基本信息的方式 (VCL/C++):

AnsiString OpenGLscreen::glinfo()
    {
    AnsiString txt="";
    txt+=glGetAnsiString(GL_VENDOR)+"\r\n";
    txt+=glGetAnsiString(GL_RENDERER)+"\r\n";
    txt+="OpenGL ver: "+glGetAnsiString(GL_VERSION)+"\r\n";
    if (ext_is_supported("GL_NVX_gpu_memory_info"))
        {
        GLint x,y,z;
        x=0; glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX,&x);
        y=0; glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX,&y);
        z=0; glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX,&z);
        txt+=AnsiString().sprintf("GPU memory: %i/%i/%i MByte\r\n",x>>10,y>>10,z>>10); // GPU free/GPU total/GPU+CPU shared total
        x=0; glGetIntegerv(GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX,&x);
        y=0; glGetIntegerv(GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX,&y);
        txt+=AnsiString().sprintf("GPU blocks: %i used: %i MByte\r\n",x,y>>10);
        }
    if (ext_is_supported("GL_ATI_meminfo"))
        {
        GLint x0,x1,x2,x3; // free,largest available block,free auxiliary, largest available auxiliary
        x0=0; glGetIntegerv(GL_VBO_FREE_MEMORY_ATI,&x0);
        x1=0; glGetIntegerv(GL_VBO_FREE_MEMORY_ATI,&x1);
        x2=0; glGetIntegerv(GL_VBO_FREE_MEMORY_ATI,&x2);
        x3=0; glGetIntegerv(GL_VBO_FREE_MEMORY_ATI,&x3);
        txt+=AnsiString().sprintf("VBO memory: %i MByte\r\n",x0>>10);
        x0=0; glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI,&x0);
        x1=0; glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI,&x1);
        x2=0; glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI,&x2);
        x3=0; glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI,&x3);
        txt+=AnsiString().sprintf("TXR memory: %i MByte\r\n",x0>>10);
        x0=0; glGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI,&x0);
        x1=0; glGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI,&x1);
        x2=0; glGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI,&x2);
        x3=0; glGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI,&x3);
        txt+=AnsiString().sprintf("BUF memory: %i MByte\r\n",x0>>10);
        }
    return txt;
    }

所以提取nVidiaATI/AMD内存查询。并移植到您的环境。

顺便说一句,我刚刚意识到要使上述代码正常工作,您还需要:

AnsiString glGetAnsiString(GLuint id)
    {
    GLubyte a,*p=(GLubyte*)(void*)glGetString(id);
    AnsiString s;
    for(s="";p;p++)
        {
        a=p[0];
        if (!a) break;
        s+=char(a);
        }
    return s;
    }

只是将 glGetString 的结果从 char* 转换为我经常使用的 VCL 的 AnsiString。因此,在与 VCL 不同的环境中,只需坚持 char* 或转换为您得到的字符串类型...