私はしばらくこれにこだわっています。これは特に高価なシェーダーではありません (少なくとも、Metal での非常に限られた経験に基づくと)、それでも最初の数フレームで次のメッセージが表示されます。
Execution of the command buffer was aborted due to an error during execution. Caused GPU Hang Error (IOAF code 3)
そして、私はこれをすべての後続のフレームに取得します:
Execution of the command buffer was aborted due to an error during execution. Ignored (for causing prior/excessive GPU errors) (IOAF code 4)
これは、実際には何もしない頂点シェーダーです。
vertex VertexOut viewportProgram(uint vertexID [[ vertex_id ]],
constant float2 *positions [[ buffer(0) ]],
constant float2 *texcoords [[ buffer(1) ]]) {
VertexOut out;
out.position.xy = positions[vertexID];
out.position.z = 0.0; // Only 2D; no depth
out.position.w = 1.0; // Only 2D; no perspective divide
out.texcoord = texcoords[vertexID];
return out;
}
YUV から RGB に色を変換するフラグメント シェーダーは次のとおりです。
fragment float4 colorConvertProgram(VertexOut in [[stage_in]],
texture2d<float, access::sample> yTexture [[ texture(0) ]],
texture2d<float, access::sample> uvTexture [[ texture(1) ]],
sampler textureSampler [[ sampler(0) ]]) {
float3 colorOffset = float3(-(16.0/255.0), -0.5, -0.5);
float3x3 colorMatrix = float3x3(float3(1.164, 0.000, 1.596),
float3(1.164, -0.392, -0.813),
float3(1.164, 2.017, 0.000));
float3 yuv = float3(yTexture.sample(textureSampler, in.texcoord).r,
uvTexture.sample(textureSampler, in.texcoord).rg);
float3 rgb = (yuv + colorOffset) * colorMatrix;
return float4(rgb, 1.0);
}
そして、これはすべてをまとめた私の Swift コードです。
let samplerDescriptor = MTLSamplerDescriptor()
samplerDescriptor.minFilter = .linear
samplerDescriptor.mipFilter = .linear
samplerDescriptor.sAddressMode = .clampToZero
samplerDescriptor.tAddressMode = .clampToZero
let sampler = device.makeSamplerState(descriptor: samplerDescriptor)
renderEncoder.setViewport(MTLViewport(originX: 0.0, originY: 0.0,
width: Double(bounds.width),
height: Double(bounds.height),
znear: -1.0, zfar: 1.0))
renderEncoder.setRenderPipelineState(renderPipelineState)
renderEncoder.setVertexBuffer(vertexPositionBuffer, offset: 0, index: 0)
renderEncoder.setVertexBuffer(vertexTexcoordBuffer, offset: 0, index: 1)
renderEncoder.setFragmentTexture(yTexture, index: 0)
renderEncoder.setFragmentTexture(uvTexture, index: 1)
renderEncoder.setFragmentSamplerState(sampler, index: 0)
renderEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
renderEncoder.endEncoding()
commandBuffer.present(drawable)
commandBuffer.commit()