2017-04-26 10 views
1

私は、時間の経過とともに粒子が増加したいと思っています。私はadviceを得て、バッファー値を高く設定して、パーティクルの量を再生することができます。私が考えているのは、バッファに最大カウントサイズを設定し、次にshaderに、粒子属性を取る配列のstructを持っています。メタルシェーディング言語 - バッファーバインディング

私は私のswiftでこれを持っている:

var vectMaxCount = 10 
var metalvects = [float3(0.0,0.0,0.0),float3(1.0,0.0,0.0),float3(2.0,0.0,0.0)] 
var vectBuffer: MTLBuffer! 

その後、私はbufferを登録します。

vectBuffer = device!.makeBuffer(length: MemoryLayout<float3>.size * vectMaxCount, options: []) 

し、それに応じてbufferを更新:

... 
command_encoder.setBuffer(vectBuffer, offset: 0, at: 2) 
var bufferPointer = vectBuffer.contents() 
memcpy(bufferPointer, &metalvects, MemoryLayout<float3>.size * vectMaxCount) 

let threadGroupCount = MTLSizeMake(8, 8, 1) 
let threadGroups = MTLSizeMake(drawable.texture.width/threadGroupCount.width, drawable.texture.height/threadGroupCount.height, 1) 
command_encoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) 
command_encoder.endEncoding() 
command_buffer.present(drawable) 
command_buffer.commit() 

やからそれを取得しようmetalファイル:

struct Vects 
{ 
    float3 position[100]; 
}; 

kernel void compute(texture2d<float, access::write> output [[texture(0)]], 
        constant Vects &vects [[buffer(2)]], 
        uint2 gid [[thread_position_in_grid]]) { 
... 
} 

と私はエラーました:私のエラーを与えるそれはラインcommand_encoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount)を示している

validateComputeFunctionArguments:727: failed assertion `(length - offset)(160) must be >= 1600 at buffer binding at index 2 for vects[0].'

を。私はbuffer bindingについて少し読んで、私は問題を与えるthreadGroupCountsまたはThreadGroupを送信する方法だと思います。

float3 position[100];float3 position[7];に変更すると、それでも機能します。それ以上のものであれば、同様のエラーが発生します。

どうすれば解決できますか?

と推定される数式はthreadGroupsthreadGroupCountですか?それを行うための経験則でさえ?ケンThomasesの答えに基づいて

Update01

は、私はに私のコードを変更します。

SWIFT:

vectBuffer = device!.makeBuffer(length: MemoryLayout<float3>.stride * metalvects.count, options: []) 
... 
memcpy(bufferPointer, &metalvects, MemoryLayout<float3>.stride * metalvects.count) 
... 

金属:

struct Vects 
{ 
    float3 position[3]; 
}; 
... 

それは今の仕事を行います。しかし、私はどのようにして、後でthis postのようなアプリケーションで使用するバッファメモリを割り当てることができますか?

答えて

1

ここには複数の問題があります。

特定のサイズのVectsを定義しています。これにより、インデックス2のバッファのサイズが、vects変数のサイズに一致するかどうかをMetalが確認できます。十分ではないので不平を言っている。 (vectsは、例えば、constant float3 *vects [[buffer(2)]]として宣言された場合には、このチェックを行うことができないだろう。)

第二に、あなたのバッファのサイズ - MemoryLayout<float3>.size * vectMaxCount - 間違っています。 float3のアラインメントと、[float3]配列の要素間に存在するパディングは考慮されません。documentation for MemoryLayoutに記載されているように、割り当てサイズを計算するときは、sizeではなく、常にstrideを使用する必要があります。

これは、Vects::positionが8以上の要素長であるために発生します。 vectMaxCountは10ですが、バッファーがvectMaxCountfloat3の配列よりも短いため、11要素から開始すると考えられます。具体的には、バッファは10 * 12 == 120バイトです。 float3のストライドは16で120/16 == 7.5です。

あなたのバッファを割り当てるときsizeからstrideに切り替えてvectMaxCountに一致するように10にVects::positionの要素数を変更する場合は、この即時の問題を乗り越えるだろう。しかし、そこにはさらに問題があります。

現在の計算機能では、実際には何個の要素が埋められているのかわかりません。vects.positionあなたは要素の実際の数を渡す必要があります。

このライン:

memcpy(bufferPointer, &metalvects, MemoryLayout<float3>.size * vectMaxCount) 

が(でもstridesizeを交換した後に)間違っています。それはmetalvectsの終わりを過ぎて読み取ります。これは、metalvectsの要素の数がvectMaxCountより少ないためです。 vectMaxCountの代わりにmetalvects.countを使用してください。

+0

update01を確認してください。私はあなたが答えた別の投稿からの参照を取っています。 – sooon

+0

バッファを割り当てるときには 'vextMaxCount'を使い続けることができます。これは、 'metalvects.count'を使うべき' memcpy() 'の呼び出しです。 –

+0

うん、それは動作します。私は 'Memory Layout'などについてもっと読む必要があります。良いアドバイスはありますか? – sooon

関連する問題