【问题标题】:Swift Int array to MetalBuffer<Int>Swift Int 数组到 MetalBuffer<Int>
【发布时间】:2022-01-13 09:14:51
【问题描述】:

我正在学习使用 swift 和 metal kit 开发应用程序

我想将一个 int 类型的数组转换为 Metalbuffer,因为我必须在 Shader.h 中覆盖该数组数据

在操作shader.h之前,数组的值没有问题。 但是,在shader.h中和之后,从数组转换而来的缓冲区存在一些问题。

例如,我将 [1, 2, 3, 4] 发送到 Metalbuffer,然后调用 renderEncoder.setVertexBuffer(Metalbuffer)。 然后,在 Shader.h 中,它看起来像 [1, 0, 2, 0] 有什么问题???

这是我的示例代码

var int_array = Array(reapeating: 1, count: 100)

init(){
    Buffers = MetalBuffer<Int>(device: device, array: int_array, index: kBuffers.rawValue, options: [])
    
}
 
func updateIntArray(){
    for i in 0..<100 {
        int_array[i] = i % 20
    }
    Buffers = MetalBuffer<Int>(device: device, array: int_array, index: kBuffers.rawValue, options: [])
    
    (other codes about rendering)
    renderEncoder.setVertexBuffer(Buffers)
}

视图控制器每帧都会调用updateIntArray。 我在着色器调用后打印了 sizeof(Buffers[i]),它是 4!

如何在不插入0的情况下保留数据?

谢谢!

【问题讨论】:

  • Metal 模块中没有MetalBuffer。您需要向我们展示这个问题的更多来源才能有意义,因为如果没有至少采用该金属缓冲区的 MetalBufferrenderEncoder.setVertexBuffer 扩展的来源,它就没有任何意义。
  • 我们还需要看一下kBuffers的代码。
  • 哦,MetalBuffer 是一个实用结构,现在我将其替换为MTLBuffer。此外,redderEncoder 被初始化为commandBuffer.makeRenderCommandEncoder(descriptor: ) 并且,kBuffers 之前被设置为ShaderTypes.h 中的某个整数!感谢您的关注,我能够解决它。谢谢!

标签: arrays swift integer metal metalkit


【解决方案1】:

您的问题中缺少很多代码,但我将向您展示如何将数组作为参数传递给片段着色器。

我有一个 ShaderTypes.h 文件来创建可用于 Swift 和 MSL(金属着色语言)的自定义值类型。如果你想在 Swift 端使用它,你需要一个桥接头。

#ifndef ShaderTypes_h
#define ShaderTypes_h
#include <simd/simd.h>

typedef struct {
    float intensity;
    float time;
    float width;
    float height;
    float originX;
    float originY;
}KeyPointValues;

我的目标是将一组 KeyPointValues 作为参数传递给我的片段着色器。在快速方面,我会做这样的事情:

var keyPoints = [KeyPointValues()]

for index in 0...10 {
   keyPoints.append(KeyPointValues())
}

var count = keyPoints.count

guard let keyPointBuffer = context.device.makeBuffer(bytes: keyPoints, length: MemoryLayout<KeyPointValues>.stride * count) else { return }

commandEncoder.setFragmentBuffer(keyPointBuffer, offset: 0, index: 0)
commandEncoder.setFragmentBytes(&count, length: MemoryLayout.size(ofValue: count), index: 1)

您还需要传入计数,因为 MSL 中没有 keyPoints.count 对应项。

那么片段着色器看起来像这样:

#include <metal_stdlib>
#include <simd/simd.h>
#import "ShaderTypes.h"

using namespace metal;

fragment half4 rosyFilter(device const KeyPointValues *keyPoints [[buffer(0)]],
                          constant uint &count [[ buffer(1) ]]
                          ) {

   for(uint index = 0; index < count; index++) {
      float intensity = keyPoints[index].intensity;
   }
}

希望这可以让您朝着正确的方向开始。您正在使用一个 Int 数组,因此它应该更容易,因为可能不需要定义在 Swift 和 MSL 之间使用的自定义结构。

我对 Metal 也有些陌生,所以我不确定这是否是最好的做事方式。我感谢有更多经验的人提供的任何反馈。

【讨论】:

  • 哦,非常感谢!实际上,只是将 Int 数组传输到 Shader.h 仍然存在我一直在说的问题。它传递由 [1, 0, 2, 0] 组成的缓冲区。所以,我创建了一个只有 int 属性的结构。 ``` #ifndef ShaderTypes_h #define ShaderTypes_h #include typedef struct { int rawval; }IntRaw; ``` 在这次试用中,你的回答很有帮助!最后,我做到了我想要的!感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-07
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多