2017-09-07 15 views
1

私はmetalでのライブフィルタのアプリケーションにtexture2d_arrayを使用しようとしています。しかし、私は適切な結果を得ていません。 Class MetalTextureArraymetalのtexture2d_array配列の使い方は?

イムは、このようなテクスチャ配列、

コードを作成します。

class MetalTextureArray { 
private(set) var arrayTexture: MTLTexture 
private var width: Int 
private var height: Int 

init(_ width: Int, _ height: Int, _ arrayLength: Int, _ device: MTLDevice) { 
    self.width = width 
    self.height = height 

    let textureDescriptor = MTLTextureDescriptor() 

    textureDescriptor.textureType = .type2DArray 
    textureDescriptor.pixelFormat = .bgra8Unorm 
    textureDescriptor.width = width 
    textureDescriptor.height = height 
    textureDescriptor.arrayLength = arrayLength 

    arrayTexture = device.makeTexture(descriptor: textureDescriptor) 
} 

func append(_ texture: MTLTexture) -> Bool { 
    if let bytes = texture.buffer?.contents() { 
     let region = MTLRegion(origin: MTLOrigin(x: 0, y: 0, z: 0), size: MTLSize(width: width, height: height, depth: 1)) 

     arrayTexture.replace(region: region, mipmapLevel: 0, withBytes: bytes, bytesPerRow: texture.bufferBytesPerRow) 

     return true 
    } 

    return false 
} 

}

イムエンコーディングこのようなrenderEncoderにこのテクスチャ、

コード:

let textureArray = MetalTextureArray.init(firstTexture!.width, firstTexture!.height, colorTextures.count, device) 

     _ = textureArray.append(colorTextures[0].texture) 
     _ = textureArray.append(colorTextures[1].texture) 
     _ = textureArray.append(colorTextures[2].texture) 
     _ = textureArray.append(colorTextures[3].texture) 
     _ = textureArray.append(colorTextures[4].texture) 

     renderEncoder.setFragmentTexture(textureArray.arrayTexture, at: 1) 

は最後に、私はこのようなフラグメントシェーダでtexture2d_arrayにアクセスしています、

コード:

私はテクスチャ配列に追加しています
struct RasterizerData { 
    float4 clipSpacePosition [[position]]; 
    float2 textureCoordinate; 

}; 

    multipleShader(RasterizerData in [[stage_in]], 
       texture2d<half> colorTexture [[ texture(0) ]], 
       texture2d_array<half> texture2D [[ texture(1) ]]) 
{ 
    constexpr sampler textureSampler (mag_filter::linear, 
             min_filter::linear, 
             s_address::repeat, 
             t_address::repeat, 
             r_address::repeat); 

    // Sample the texture and return the color to colorSample 

    half4 colorSample = colorTexture.sample (textureSampler, in.textureCoordinate); 

    float4 outputColor; 

    half red = texture2D.sample(textureSampler, in.textureCoordinate, 2).r; 
    half green = texture2D.sample(textureSampler, in.textureCoordinate, 2).g; 
    half blue = texture2D.sample(textureSampler, in.textureCoordinate, 2).b; 

    outputColor = float4(colorSample.r * red, colorSample.g * green, colorSample.b * blue, colorSample.a); 

    // We return the color of the texture 
    return outputColor; 
} 

テクスチャは、私が2として最後の引数を与えたこのコードhalf red = texture2D.sample(textureSampler, in.textureCoordinate, 2).r;ではサイズ256 * 1

であるACV曲線ファイルから抽出されたテクスチャですので、私はそれをアクセスするテクスチャのインデックスと考えました。しかし、私はそれが何を意味するのか分からない。

しかし、これらのすべてを行った後、私は黒い画面を取得しています。私は他のフラグメントシェーダを持っていて、それらのすべてがうまく動作しています。しかし、このフラグメントシェイダーのために私は黒い画面を表示しています。私はこのコードのために考えるhalf blue = texture2D.sample(textureSampler, in.textureCoordinate, 2).b私はすべての赤、緑、青の値の0を得ています。

編集1:

としては、私は質感とまだ結果をコピーするためにblitcommandEncoderを使用し提案しました。私のコードをここに

マイMetalTextureArrayクラスは修正を歩んできました。

メソッドappendはこのようになります。

func append(_ texture: MTLTexture) -> Bool { 
    self.blitCommandEncoder.copy(from: texture, sourceSlice: 0, sourceLevel: 0, sourceOrigin: MTLOrigin(x: 0, y: 0, z: 0), sourceSize: MTLSize(width: texture.width, height: texture.height, depth: 1), to: self.arrayTexture, destinationSlice: count, destinationLevel: 0, destinationOrigin: MTLOrigin(x: 0, y: 0, z: 0)) 
    count += 1 
    return true 
} 

とIM私のシェーダコードは、この

let textureArray = MetalTextureArray.init(256, 1, colorTextures.count, device, blitCommandEncoder: blitcommandEncoder) 
for (index, filter) in colorTextures!.enumerated() { 
    _ = textureArray.append(colorTextures[index].texture) 
} 
renderEncoder.setFragmentTexture(textureArray.arrayTexture, at: 1) 

のようなテクスチャを追加それでも私は黒い画面を取得し、この

multipleShader(RasterizerData in [[stage_in]], 
       texture2d<half> colorTexture [[ texture(0) ]], 
       texture2d_array<float> textureArray [[texture(1)]], 
       const device struct SliceDataSource &sliceData [[ buffer(2) ]]) 
{ 
    constexpr sampler textureSampler (mag_filter::linear, 
             min_filter::linear); 

    // Sample the texture and return the color to colorSample 
    half4 colorSample = colorTexture.sample (textureSampler, in.textureCoordinate); 

    float4 outputColor = float4(0,0,0,0); 

    int slice = 1; 


float red = textureArray.sample(textureSampler, in.textureCoordinate, slice).r; 
float blue = textureArray.sample(textureSampler, in.textureCoordinate, slice).b; 
float green = textureArray.sample(textureSampler, in.textureCoordinate, slice).g; 

outputColor = float4(colorSample.r * red, colorSample.g * green, colorSample.b * blue, colorSample.a); 

    // We return the color of the texture 
    return outputColor; 
} 

のようになります。

textureArray.sample(textureSampler, in.textureCoordinate, slice);メソッドでは、3番目のパラメータは何ですか。私はそれをインデックスとして使っていましたが、ランダムなテクスチャを取得するためにランダムなインデックスをいくつか与えました。それが正しいか?

編集2:別のエンコーダが実装され、IはACV負フィルターで次の画面を持っている前

提案を実現するために、私が最後にできると私はendEncoding方法を使用して結果を得ました。

enter image description here

誰かが私に示唆することができます。

ありがとうございました。

答えて

1

テクスチャの配列と配列テクスチャには違いがあります。あなたにはテクスチャの配列がほしいと思うように私には聞こえます。その場合は、texture2d_arrayを使用しないでください。 array<texture2d<half>, 5> texture_array [[texture(1)]]を使用してください。

setFragmentTexture()に複数の呼び出しを使用して順次インデックスにテクスチャを割り当てるか、setFragmentTextures()を使用して一度にさまざまなインデックスにテクスチャを割り当てることができます。

シェーダコードでは、配列のサブスクリプト構文を使用して配列内の個々のテクスチャを参照します(例:texture_array[2])。

実際に配列テクスチャを使用する場合は、おそらくappend()メソッドを変更する必要があります。まず、makeTexture(descriptor:offset:bytesPerRow:)メソッドがMTLBuffertexture引数が作成されなかった場合、texture.bufferは常にnilになります。つまり、テクスチャは元々バッファから作成されたものであれば関連するバッファのみを持っています。テクスチャからテクスチャにコピーするには、blitコマンドエンコーダとそのcopy(from:sourceSlice:sourceLevel:sourceOrigin:sourceSize:to:destinationSlice:destinationLevel:destinationOrigin:)メソッドを使用する必要があります。

第2に、配列テクスチャの特定のスライス(配列要素)のテクスチャデータを置き換える場合は、そのスライスインデックスをreplace()メソッドの引数として渡す必要があります。そのためには、replace(region:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage:)メソッドを使用する必要があります。現在はreplace(region:mipmapLevel:withBytes:bytesPerRow:)ではありません。現在のコードでは、最初のスライスを何度も何度も置き換えています(ソーステクスチャが実際にバッファに関連付けられていることを前提とします)。

+0

'constant array ,5> texture_array [[texture(1)]]'を使用しましたが、 'Uknown type array'というエラーが発生しています。実際に私は以前にそれを使用しようとしましたが、同じエラーが発生し、 'texture2d_array'を使用する必要がありました。なぜこのエラーを出すのか、私にお勧めできますか?それはコンパイラのためですか?もう1つのことは、テクスチャを 'UnsafeMutablePointer'に変換する方法を知ることができますか? –

+0

どのSDKとデプロイメントターゲットを使用していますか?ターゲットのビルド設定については、Metal言語のリビジョンは何ですか?テクスチャ配列は、GPUファミリ3以上(およびmacOS 10.13+)のiOS 10以降でのみ使用できます。テクスチャを 'UnsafeMutablePointer'にどこで変換したいですか? 'setFragmentTextures()'を考えているなら、Swift配列やテクスチャを渡すだけで、自動的に変換が行われます。 –

+0

私はiOS 9をサポートしようとしています。だから、私のフラグメントシェーダーの内部にテクスチャのような配列を使用することは可能です。そして、私は 'arrayTexture.replace(region:region、mipmapLevel:0、slice:4、withBytes:bytes、bytesPerRow:texture.bufferBytesPerRow、bytesPerImage:texture.bufferBytesPerRow * textureのメソッドで' UnsafeMutablePointer'にテクスチャを変換したいと思います。 .height) 'withBytesパラメータは' UnsafeMutablePointer'を期待するためです。だから、私に示唆することができます。 –

関連する問題