title: Metal: using multiple MTLRenderCommandEncoder in one rendering pass
body: <p>I am starting to play with Metal (currently my app is working with OpenGL). I am trying to check how to render with multiple pipeline states (multiple metal functions) in one rendering pass. The problem is that always only the last MTLRenderCommandEncoder is actually drawn. The following is my code:</p>
  
  <pre><code>@property (nonatomic, strong) UIView* metalView;
  
  @property (nonatomic, strong) id &lt;MTLDevice&gt; mtlDevice;
  @property (nonatomic, strong) id &lt;MTLCommandQueue&gt; mtlCommandQueue;
  @property (nonatomic, strong) MTLRenderPassDescriptor *mtlRenderPassDescriptor;
  @property (nonatomic, strong) CAMetalLayer *metalLayer;
  @property (nonatomic, strong) id &lt;CAMetalDrawable&gt; frameDrawable;
  @property (nonatomic, strong) CADisplayLink *displayLink;
  
  @property (nonatomic, strong) MTLRenderPipelineDescriptor *renderPipelineDescriptor;
  @property (nonatomic, strong) MTLRenderPipelineDescriptor *renderPipelineDescriptorb;
  
  @property (nonatomic, strong) id &lt;MTLRenderPipelineState&gt; renderPipelineState;
  @property (nonatomic, strong) id &lt;MTLRenderPipelineState&gt; renderPipelineStateb;
  @property (nonatomic, strong) id &lt;MTLBuffer&gt; object;
  @property (nonatomic, strong) id &lt;MTLBuffer&gt; objectb;
  
  @end
  
  @implementation MetalGPUAdapter
  
  - (void)setupGraphics
  {
      self.mtlDevice = MTLCreateSystemDefaultDevice();
      self.mtlCommandQueue = [self.mtlDevice newCommandQueue];
  
      self.metalLayer = [CAMetalLayer layer];
      [self.metalLayer setDevice:self.mtlDevice];
      [self.metalLayer setPixelFormat:MTLPixelFormatBGRA8Unorm];
      self.metalLayer.framebufferOnly = YES;
      [self.metalLayer setFrame:self.gpuViewController.view.layer.frame];
  
      self.metalView = [[UIView alloc] initWithFrame:self.gpuViewController.view.frame];
      [self.gpuViewController.view addSubview:self.metalView];
      [self.gpuViewController.view sendSubviewToBack:self.metalView];
  
      [self.metalView.layer addSublayer:self.metalLayer];
      [self.metalView setOpaque:YES];
      [self.metalView setBackgroundColor:nil];
      [self.metalView setContentScaleFactor:[UIScreen mainScreen].scale];
  
      // Create a reusable pipeline
      self.renderPipelineDescriptor = [MTLRenderPipelineDescriptor new];
      self.renderPipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
  
      self.renderPipelineDescriptorb = [MTLRenderPipelineDescriptor new];
      self.renderPipelineDescriptorb.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
  
      id &lt;MTLLibrary&gt; lib = [self.mtlDevice newDefaultLibrary];
      self.renderPipelineDescriptor.vertexFunction = [lib newFunctionWithName:@"VertexColor"];
      self.renderPipelineDescriptor.fragmentFunction = [lib newFunctionWithName:@"FragmentColor"];
      self.renderPipelineState = [self.mtlDevice newRenderPipelineStateWithDescriptor:self.renderPipelineDescriptor error: nil];
  
      self.renderPipelineDescriptorb.vertexFunction = [lib newFunctionWithName:@"VertexColorb"];
      self.renderPipelineDescriptorb.fragmentFunction = [lib newFunctionWithName:@"FragmentColorb"];
      self.renderPipelineStateb = [self.mtlDevice newRenderPipelineStateWithDescriptor:self.renderPipelineDescriptorb error: nil];
  
      Triangle triangle[3] = { { -1.0f, -1.0f }, { 1.0f, -1.0f }, { 0.0f, 0.0f } };
      Triangle square[4] = { { -1.0f, 0.0f }, { -1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }};
  
      self.object = [self.mtlDevice newBufferWithBytes:&amp;triangle length:sizeof(Triangle[3]) options:MTLResourceOptionCPUCacheModeDefault];
      self.objectb = [self.mtlDevice newBufferWithBytes:&amp;square length:sizeof(Triangle[4]) options:MTLResourceOptionCPUCacheModeDefault];
  
      self.displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(renderScene)];
      [self.displayLink addToRunLoop: [NSRunLoop currentRunLoop] forMode: NSDefaultRunLoopMode];
  }
  
  - (void)renderScene
  {
      id &lt;MTLCommandBuffer&gt;mtlCommandBuffer = [self.mtlCommandQueue commandBuffer];
  
      while (!self.frameDrawable){
          self.frameDrawable = [self.metalLayer nextDrawable];
      }
  
      if (!self.mtlRenderPassDescriptor)
          self.mtlRenderPassDescriptor = [MTLRenderPassDescriptor new];
  
      self.mtlRenderPassDescriptor.colorAttachments[0].texture = self.frameDrawable.texture;
      self.mtlRenderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
      self.mtlRenderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.75, 0.5, 1.0, 1.0);
      self.mtlRenderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
  
      id &lt;MTLRenderCommandEncoder&gt; renderCommand = [mtlCommandBuffer renderCommandEncoderWithDescriptor: self.mtlRenderPassDescriptor];
  
      [renderCommand setRenderPipelineState:self.renderPipelineStateb];
      [renderCommand setVertexBuffer:self.object offset:0 atIndex:0];
      [renderCommand drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3];
  
      [renderCommand endEncoding];
  
      id &lt;MTLRenderCommandEncoder&gt; renderCommandb = [mtlCommandBuffer renderCommandEncoderWithDescriptor: self.mtlRenderPassDescriptor];
  
      [renderCommandb setRenderPipelineState:self.renderPipelineStateb];
      [renderCommandb setVertexBuffer:self.objectb offset:0 atIndex:0];
      [renderCommandb drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
  
      [renderCommandb endEncoding];
  
  
      [mtlCommandBuffer presentDrawable: self.frameDrawable];
      [mtlCommandBuffer commit];
      self.mtlRenderPassDescriptor = nil;
      self.frameDrawable = nil;
  }
  </code></pre>
  
  <p>My shaders:</p>
  
  <pre><code>#include &lt;metal_stdlib&gt;
  using namespace metal;
  
  typedef struct {
      float2 position;
  } Triangle;
  
  typedef struct {
      float4 position [[position]];
  } TriangleOutput;
  
  vertex TriangleOutput VertexColor(const device Triangle *Vertices [[buffer(0)]], const uint index [[vertex_id]])
  {
      TriangleOutput out;
      out.position = float4(Vertices[index].position, 0.0, 1.0);
      return out;
  }
  
  vertex TriangleOutput VertexColorb(const device Triangle *Vertices [[buffer(0)]], const uint index [[vertex_id]])
  {
      TriangleOutput out;
      out.position = float4(Vertices[index].position, 0.0, 1.0);
      return out;
  }
  
  fragment half4 FragmentColor(void)
  {
      return half4(1.0, 0.0, 0.0, 1.0);
  }
  
  fragment half4 FragmentColorb(void)
  {
      return half4(1.0, 0.0, 1.0, 1.0);
  }
  </code></pre>