金属GPU缓冲区与CPU不同步

时间:2018-01-21 12:56:25

标签: swift metal

我正在尝试从场景中添加多个对象,从Xcode 9的Metal Game App模板开始。

我已经根据这个答案尽可能少地修改了默认游戏模板,以渲染多个对象:https://stackoverflow.com/a/37424817/518169

我的问题是没有出现第二个对象。添加打印行显示缓冲区在CPU上更新,但使用GPU帧捕获我可以看到GPU上没有。实际上发生的是第二个立方体的状态用于两个绘制调用。使用// left cube var modelMatrix = matrix4x4_translation(-3, 0, 0) var viewMatrix = matrix4x4_translation(0.0, 0.0, -8.0) uniforms[0].modelViewMatrix = simd_mul(viewMatrix, modelMatrix) print(uniforms[0]) for submesh in mesh.submeshes { renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType, indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer, indexBufferOffset: submesh.indexBuffer.offset) } // right cube modelMatrix = matrix4x4_translation(3, 0, 0) viewMatrix = matrix4x4_translation(0.0, 0.0, -8.0) uniforms[0].modelViewMatrix = simd_mul(viewMatrix, modelMatrix) print(uniforms[0]) for submesh in mesh.submeshes { renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType, indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer, indexBufferOffset: submesh.indexBuffer.offset) } 时,这不会发生。

最小案例:Xcode 9 /使用Metal的新跨平台游戏,并将drawIndexedPrimitives部分替换为:

let alignedUniformsSize = (MemoryLayout<Uniforms>.size & ~0xFF) + 0x100
let maxBuffersInFlight = 3

class Renderer: NSObject, MTKViewDelegate {
  var dynamicUniformBuffer: MTLBuffer
  let inFlightSemaphore = DispatchSemaphore(value: maxBuffersInFlight)
  var uniformBufferOffset = 0
  var uniformBufferIndex = 0
  var uniforms: UnsafeMutablePointer<Uniforms>

  init?(metalKitView: MTKView) {
    let uniformBufferSize = alignedUniformsSize * maxBuffersInFlight
    guard let buffer = self.device.makeBuffer(length: uniformBufferSize, options: [MTLResourceOptions.storageModeShared]) else { return nil }
    dynamicUniformBuffer = buffer
    uniforms = UnsafeMutableRawPointer(dynamicUniformBuffer.contents()).bindMemory(to: Uniforms.self, capacity: 1)
  }

  private func updateDynamicBufferState() {
    uniformBufferIndex = (uniformBufferIndex + 1) % maxBuffersInFlight
    uniformBufferOffset = alignedUniformsSize * uniformBufferIndex
    uniforms = UnsafeMutableRawPointer(dynamicUniformBuffer.contents() + uniformBufferOffset).bindMemory(to: Uniforms.self, capacity: 1)
  }

  func draw(in view: MTKView) {
    _ = inFlightSemaphore.wait(timeout: DispatchTime.distantFuture)
    if let commandBuffer = commandQueue.makeCommandBuffer() {
      let semaphore = inFlightSemaphore
      commandBuffer.addCompletedHandler { (_) -> Swift.Void in semaphore.signal()}

      updateDynamicBufferState()
      updateGameState()

      if let renderPassDescriptor = view.currentRenderPassDescriptor, let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) {
        renderEncoder.setCullMode(.back)
        renderEncoder.setRenderPipelineState(pipelineState)
        renderEncoder.setVertexBuffer(dynamicUniformBuffer, offset: uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
        renderEncoder.setFragmentBuffer(dynamicUniformBuffer, offset: uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
        for (index, element) in mesh.vertexDescriptor.layouts.enumerated() {
          guard let layout = element as? MDLVertexBufferLayout else {return}
          if layout.stride != 0 {
            let buffer = mesh.vertexBuffers[index]
            renderEncoder.setVertexBuffer(buffer.buffer, offset: buffer.offset, index: index)
          }
        }
        renderEncoder.setFragmentTexture(colorMap, index: TextureIndex.color.rawValue)

        // left cube
        var modelMatrix = matrix4x4_translation(-3, 0, 0)
        var viewMatrix = matrix4x4_translation(0.0, 0.0, -8.0)
        uniforms[0].modelViewMatrix = simd_mul(viewMatrix, modelMatrix)
        print(uniforms[0])
        for submesh in mesh.submeshes {
          renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType, indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer, indexBufferOffset: submesh.indexBuffer.offset)
        }

        // right cube
        modelMatrix = matrix4x4_translation(3, 0, 0)
        viewMatrix = matrix4x4_translation(0.0, 0.0, -8.0)
        uniforms[0].modelViewMatrix = simd_mul(viewMatrix, modelMatrix)
        print(uniforms[0])
        for submesh in mesh.submeshes {
          renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType, indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer, indexBufferOffset: submesh.indexBuffer.offset)
        }

        renderEncoder.endEncoding()
        if let drawable = view.currentDrawable {
          commandBuffer.present(drawable)
        }
      }
      commandBuffer.commit()
    }
  }
}

完整文件的框架如下所示(供将来参考):

{{1}}

0 个答案:

没有答案