首页 文章

在Metal中手动设置1D纹理

提问于
浏览
1

我正在尝试手动填充 1D texture 并将该纹理传递给计算着色器(这些是我想通过代码设置的2个像素,它们不代表任何图像) .

由于当前少量的Metal示例,我可以找到的所有示例都处理 2D textures ,它通过将加载的 UIImage 转换为原始字节数据来加载纹理,但创建一个虚拟 UIImage 对我来说就像是一个黑客 .

这是我开始的“天真”方式 -

...
var manualTextureData: [Float] = [ 1.0, 0.0, 0.0, 1.0,
                                   0.0, 0.0, 1.0, 1.0 ];
let region: MTLRegion = MTLRegionMake1D(0, textureDescriptor.width);
myTexture.replaceRegion(region, mipmapLevel: 0, withBytes: &manualTextureData, bytesPerRow: 0);

但是金属无法识别着色器中的那些值(除第一个值外,它会获得空纹理) .

我很快意识到Float数组可能必须转换为字节数组(例如 UInt8 ),但无法找到从 [Float] 转换为 [UInt8] 的方法 .

我考虑的另一个可能的选择是使用 CVPixelBuffer 对象,但这也是解决问题的方法 .

那么解决这个问题的正确方法是什么?

提前致谢 .

  • 请注意我对 Objective-C 并不熟悉,因此我不确定使用 CVPixelBuffer / UIImage 是否被夸大了应该是直截了当的事情 .

4 回答

  • 0

    我没有看到你使用1D纹理传递数据的任何理由 . 相反,我只会传递一个缓冲区 . 像这样:

    var dataBuffer:MTLBuffer? = device.newBufferWithBytes(&manualTextureData, length: sizeOf(manualTextureData), options: MTLResourceOptions.OptionCPUCacheModeDefault)
    

    然后你把它挂钩到你的 renderCommandEncoder

    renderCommandEncoder.setFragmentBuffer(dataBuffer, offset: 0, atIndex: 1)//Note that if you want this buffer to be passed to you vertex shader you should use setVertexBuffer
    

    然后在你的着色器中,你应该添加像这样的参数 const device float* bufferPassed [[ buffer(1) ]]

    然后在着色器实现中使用它:

    float firstFloat = bufferPassed[0];
    

    这将完成工作 .

  • 0

    并没有真正回答你的问题,但你可以在金属着色器中定义一个数组,而不是将值作为纹理传递 .

    就像是:

    constant float manualData[8] = { 1.0, 0.0, 0.0, 1.0,
                                   0.0, 0.0, 1.0, 1.0 };
    
    vertex float4 world_vertex(unsigned int vid[[vertex_id]], ...) {
        int manualIndex = vid % 8;
        float manualValue = manualData[manualIndex];
        // something deep and meaningful here...
        return float4(manualValue);
    }
    
  • 0

    如果你想浮点纹理bytesPerRow应该是宽度的4倍,因为浮点数的大小为4个字节 . 金属复制内存,不关心值 . 那是你的任务;-)

    就像是:

    myTexture.replaceRegion(region, mipmapLevel: 0, withBytes: &manualTextureData, bytesPerRow: manualTextureData.count * sizeof(Float));
    
  • 0

    请原谅简洁的回复,但您可能会发现使用Swift和Metal查看我的实验很有用 . 我在Swift中创建了一个粒子系统,它作为粒子结构的一维数组传递给Metal计算着色器 . 通过使用posix_memalign,我能够消除在Metal和Swift之间传递数组所造成的瓶颈 .

    我在博客上写了很多关于此的内容:http://flexmonkey.blogspot.co.uk/search/label/Metal

    我希望这有帮助 .

    西蒙

相关问题