代码之家  ›  专栏  ›  技术社区  ›  Makogan

3D纹理大小影响程序输出,不会引发错误

  •  2
  • Makogan  · 技术社区  · 6 年前

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

    其次,我正在分配3D纹理存储,如下所示:

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

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

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

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

    是否有一种方法可以验证我确实请求的内存超过了可以分配的内存,并以某种方式扩展了所述内存?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Spektre    3 年前

    是的,如果我计算正确的话,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;
        }
    

    所以提取 英伟达 ATI/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字符* 或者转换为字符串类型。。。