[英]Is there a memory leak via texture2D in a fragment shader on ios?
我正在使用Brad Larson的GPUImage库,并且我认为我发现了一个有趣的问题。
以下着色器程序执行得很好:
NSString *const kDilationFragmentShaderString = SHADER_STRING
(
precision highp float;
uniform int height;
uniform int width;
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform int radius;
void main (void)
{
vec2 uv = textureCoordinate;
vec2 theSize = vec2(width, height);
vec3 theMax = texture2D(inputImageTexture, uv).rgb;
gl_FragColor = vec4(theMax, 1.0);
}
);
但是,此版本在大型图像上会崩溃(例如,相机的4x3图像在最长的一侧调整为2560)。 在我看来,唯一不同的是Texture2D调用集:
NSString *const kDilationFragmentShaderString = SHADER_STRING
(
precision highp float;
uniform int height;
uniform int width;
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform int radius;
void main (void)
{
vec2 uv = textureCoordinate;
vec2 theSize = vec2(width, height);
vec3 theMax = texture2D(inputImageTexture, uv).rgb;
int i;
int j;
int radsqr = radius*radius;
for (j = -radius; j <= radius; ++j) {
for (i = -radius; i <= radius; ++i) {
if (i * i + j * j > radsqr) continue;
theMax = max(theMax, texture2D(inputImageTexture, uv + vec2(i,j)/theSize).rgb);
}
}
gl_FragColor = vec4(theMax, 1.0);
}
);
我正在运行此过滤器,然后运行第二个过滤器,该过滤器的最小值(即,形态膨胀然后是侵蚀或形态关闭运算符)。
我确实意识到,实现此目标的最佳方法是尝试通过顶点着色器将所有texture2D调用放到自己的位置。 但是,如果半径为10,则需要314个顶点,超过了允许的位置数。 如果我在模拟器中运行这些命令,并且所有其他条件都相等,那么第一个命令就可以完成,但是第二个代码会消耗内存,并且调用侵蚀过滤器时内存会急剧增加。 在iPhone 4s上运行,第一个代码片段可以正常运行(当然很快),但是第二个代码片段在膨胀后崩溃,并且不运行侵蚀调用。
最初,似乎Texture2D正在泄漏; 但是,这些函数在线程中被调用。 当线程退出时,模拟器中的所有内存将被清除。 因此,如果这些功能第一次正确运行,则可以多次运行而不会出现问题。
所以我的问题是:在那里执行Texture2D调用可能会导致此行为? 一旦过滤器完成,是否有一种方法可以刷新创建的任何缓冲区,而与结束两次调用之间的线程无关?
编辑:自发布此问题以来,我在一周内学到了一些东西:问题在于for循环本身。 删除for循环,然后内存问题消失。 那是,
NSString *const kDilationFragmentShaderString = SHADER_STRING
(
precision highp float;
uniform int height;
uniform int width;
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform int radius;
void main (void)
{
vec2 uv = textureCoordinate;
vec2 theSize = vec2(width, height);
vec3 theMax = texture2D(inputImageTexture, uv).rgb;
int i;
int j;
int radsqr = radius*radius;
for (j = -radius; j <= radius; ++j) {
for (i = -radius; i <= radius; ++i) {
}
}
gl_FragColor = vec4(theMax, 1.0);
}
);
将分配尽可能多的内存,就好像在循环内发生了什么一样。 我正在通过模拟器上的检查器确定此行为。 当我在1280x1280图像上运行不带for循环的着色器时,总共分配了202 mb的内存;当我带for循环运行它时,无论for循环内部发生了什么,都分配了230 mb。 While循环也会发生相同的行为。
如果要刷新内容,可以调用glFlush()
,它将刷新当前上下文的OpenGL命令队列。 您可以做的另一件事是平铺图像并一次处理较小的部分。 这就是Photoshop,Final Cut Pro等应用程序的工作方式,并且内存效率很高。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.