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

3D texture size affecting program output without error being thrown

本文关键字:错误 程序 纹理 影响 3D 输出      更新时间:2023-10-16

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

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

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

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

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

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

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

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

AnsiString OpenGLscreen::glinfo()
{
AnsiString txt="";
txt+=glGetAnsiString(GL_VENDOR)+"rn";
txt+=glGetAnsiString(GL_RENDERER)+"rn";
txt+="OpenGL ver: "+glGetAnsiString(GL_VERSION)+"rn";
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 MBytern",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 MBytern",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 MBytern",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 MBytern",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 MBytern",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*转换为我大量使用的VCLAnsiString。因此,在与VCL不同的环境中,只需坚持使用char*或转换为您得到的字符串类型即可...