繁体   English   中英

在iOS的片段着色器中是否通过Texture2D发生内存泄漏?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM