title: Flickering Metal output texture... Why?
body: <p>I am attempting to place a number of overlays (textures) on top of an existing texture.  For the most part, this works fine.</p>
  
  <p>However, for the life of me, I can't figure out why the output of this is sporadically "flickering" in my <code>drawRect</code> method of my <code>MTKView</code>.  Everything seems fine; I do further processing on <code>theTexture</code> (in a kernel shader) after I loop with my placing my overlays.  For some reason, I feel like this encoding is ending early and not enough work is getting done on it.</p>
  
  <p>To clarify, everything starts out fine but about 5 seconds in, the flickering starts and gets progressively worse.  For debugging purposes (right now, anyways) that loop runs only once -- there is only one overlay element. The input texture (<code>theTexture</code>) is bona-fide every time before I start (created with a descriptor where storageMode is <code>MTLStorageModeManaged</code> and usage is <code>MTLTextureUsageUnknown</code>).</p>
  
  <p>I've also tried stuffing the encoder instantiation/ending inside the loop; no difference.</p>
  
  <p><strong>Can someone help me see what I'm doing wrong?</strong></p>
  
  <pre><code>id&lt;MTLTexture&gt; theTexture; // valid input texture as "background"
  
  MTLRenderPassDescriptor *myRenderPassDesc = [MTLRenderPassDescriptor renderPassDescriptor];
  myRenderPassDesc.colorAttachments[0].texture = theTexture;
  myRenderPassDesc.colorAttachments[0].storeAction = MTLStoreActionStore;
  myRenderPassDesc.colorAttachments[0].loadAction = MTLLoadActionLoad;
  
  id&lt;MTLRenderCommandEncoder&gt; myEncoder = [commandBuffer renderCommandEncoderWithDescriptor:myRenderPassDesc];
  MTLViewport viewPort = {0.0, 0.0, 1920.0, 1080.0, -1.0, 1.0};
  vector_uint2 imgSize = vector2((u_int32_t)1920,(u_int32_t)1080);
  [myEncoder setViewport:viewPort];
  [myEncoder setRenderPipelineState:metalVertexPipelineState];
  
  for (OverlayWrapper *ow in overlays) {
      id&lt;MTLTexture&gt; overlayTexture = ow.overlayTexture;
  
      VertexRenderSet *v = [ow getOverlayVertexInfoPtr];
      NSUInteger vSize = v-&gt;metalVertexCount*sizeof(AAPLVertex);
      id&lt;MTLBuffer&gt; mBuff = [self.device newBufferWithBytes:v-&gt;metalVertices
                                                     length:vSize
                                                    options:MTLResourceStorageModeShared];
  
      [myEncoder setVertexBuffer:mBuff offset:0 atIndex:0];
      [myEncoder setVertexBytes:&amp;imgSize length:sizeof(imgSize) atIndex:1];
      [myEncoder setFragmentTexture:overlayTexture atIndex:0];
      [myEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:v-&gt;metalVertexCount];
  }
  
  [myEncoder endEncoding];
  
  // do more work (kernel shader) with "theTexture"...
  </code></pre>
  
  <hr>
  
  <hr>
  
  <p><strong>UPDATE #1:</strong>
  I've attached a image of a "good" frame, with the vertex area (lower right) being shown.  My encoder is responsible for placing the green stand-in "image" on top of the video frame <code>theTexture</code> at 30fps, which it does do.  Just to clarify, <code>theTexture</code> is created for each frame (from a CoreVideo pixel buffer).  After this encoder, I only read from the <code>theTexture</code> in a kernel shader to adjust brightness -- all that is working just fine.</p>
  
  <p><strike>My problems must exist elsewhere, as the video frames stop flowing (though the audio keeps going) and I end up alternating between 2 or 3 previous frames once this encoder is inserted (hence, the flicker). I believe now that my video pixel buffer vendor is being inadvertently supplanted by this "overlay" vendor.</strike></p>
  
  <p>If I comment out this entire vertex renderer, my video frames flow through just fine; it's NOT a problem with my video frame vendor.</p>
  
  <h2><img src="https://i.stack.imgur.com/zG5dp.png" alt="A sample &quot;good&quot; frame of video[1]"></h2>
  
  <p><strong>UPDATE #2:</strong></p>
  
  <p>Here is the declaration of my rendering pipeline:</p>
  
  <pre><code>MTLRenderPipelineDescriptor *p = [[MTLRenderPipelineDescriptor alloc] init];
  if (!p)
      return nil;
  p.label = @"Vertex Mapping Pipeline";
  p.vertexFunction   = [metalLibrary newFunctionWithName:@"vertexShader"];
  p.fragmentFunction = [metalLibrary newFunctionWithName:@"samplingShader"];
  p.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
  
  NSError *error;
  metalVertexPipelineState = [self.device newRenderPipelineStateWithDescriptor:p
                                                                         error:&amp;error];
  if (error || !metalVertexPipelineState)
      return nil;
  </code></pre>
  
  <p>Here is the texture descriptor used for creation of <code>theTexture</code>:</p>
  
  <pre><code>metalTextureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm 
                                                                              width:width
                                                                             height:height
                                                                          mipmapped:NO];
  metalTextureDescriptor.storageMode = MTLStorageModePrivate;
  metalTextureDescriptor.usage = MTLTextureUsageUnknown;
  </code></pre>
  
  <p>I haven't included the <code>AAPLVertex</code> and the vertex/fragment functions because of this:  If I just comment out the <code>OverlayWrapper</code> loop in my rendering code (ie. don't even set vertex buffers or draw primitives), the video frames still flicker.  The video is still playing but only 2-3 frames or so are playing in a continuous loop, from the time that this encoder "ran".</p>
  
  <p>I've also added this code after the <code>[... endEncoding]</code> and changed the texture usage to <code>MTLStorageModeManaged</code> -- still, no dice:</p>
  
  <pre><code>id&lt;MTLBlitCommandEncoder&gt; blitEncoder = [commandBuffer blitCommandEncoder];
  [blitEncoder synchronizeResource:crossfadeOutput];
  [blitEncoder endEncoding];
  </code></pre>
  
  <p>To clarify a few things: The subsequent computer shader uses <code>theTexture</code> for input only.  These are video frames; thusly, <code>theTexture</code> is re-created each time.  Before it goes through this render stage, it has a bona-fide "background"</p>
  
  <hr>
  
  <p><strong>UPDATE #3:</strong></p>
  
  <p>I got this working, if by unconventional means.</p>
  
  <p>I used this vertex shader to render my overlay onto a transparent background of a newly-created blank texture, specifically with my <code>loadAction</code> being <code>MTLLoadActionClear</code> with a clearColor of (0,0,0,0).  </p>
  
  <p>I then mixed this resulting texture with my <code>theTexture</code> with a kernel shader.  I should <strong>not</strong> have to do this, but it works!</p>