将纹理数组发送到Metal的最佳方法

时间:2015-04-15 21:58:59

标签: ios metal

我已经获得了以下着色器(为了长度和清晰度而移除了碎片),并希望找到更好的方法来执行此操作。我想将一个大小可变的纹理数组发送到我的金属着色器。我将对顶点位置进行一些计算,然后确定要使用的纹理。

目前我只是硬编码并使用了几个if语句,但这很难看(而且我猜不快)。我有什么方法可以计算i,然后使用i作为纹理下标(如tex[i].sample)?

// Current code - its ugly
fragment half4 SimpleTextureFragment(VertextOut inFrag [[stage_in]],
                                   texture2d<half>  tex0   [[ texture(0) ]]
                                   texture2d<half>  tex1   [[ texture(1) ]]
                                   texture2d<half>  tex2   [[ texture(2) ]]
                                   ...
                                   texture2d<half>  texN   [[ texture(N) ]]
                                     )
{
   constexpr sampler quad_sampler;
   int i = (Compute_Correct_Texture_to_Use);
   if(i==0)
   {
      half4 color = tex0.sample(quad_sampler, inFrag.tex_coord);
   }
   else if(i==1)
   {
      half4 color = tex1.sample(quad_sampler, inFrag.tex_coord);
   }
   ...
   else if(i==n)
   {
      half4 color = texN.sample(quad_sampler, inFrag.tex_coord);
   }
   return color;
}

1 个答案:

答案 0 :(得分:2)

你的方法不会很快你是对的。最好的情况是,着色器将有很多分支(这是不好的),更糟糕的情况下,着色器实际上将从所有纹理中采样,然后丢弃它不使用的结果(这将更慢)。

这不是GPU处理得特别好的情况,所以我的建议是稍微重构你的方法以更加GPU友好。如果不了解更多关于你在更高层次上做了什么,我的第一个建议是考虑使用 2d数组纹理

2d数组纹理基本上将X 2D纹理合并到具有X切片的单个纹理中。您只需要将单个纹理传递给Metal,您就可以完全按照您的方式计算着色器中要采样的切片,但是使用这种方法,您将摆脱所有&#39; if&#39;分支,只需要像这样调用一次样本:tex.sample( my_sampler, inFrag.tex_coord, i );

如果您的纹理大小和格式都相同,那么这将非常容易。您只需将每个2D纹理复制到数组纹理的切片中即可。如果您的纹理大小或格式不同,您可能需要通过拉伸一些来解决这些问题,以便它们都以相同的尺寸结束。

请点击此处查看文档:{​​{3}} (寻找&#39;纹理切片&#39;)

此处:https://developer.apple.com/library/ios/documentation/Miscellaneous/Conceptual/MetalProgrammingGuide/Mem-Obj/Mem-Obj.html#//apple_ref/doc/uid/TP40014221-CH4-SW10

此处使用金属着色器语言文档:https://developer.apple.com/library/prerelease/ios/documentation/Metal/Reference/MTLTexture_Ref/index.html#//apple_ref/c/econst/MTLTextureType2DArray(查找&#39; 2D纹理数组&#39;)