mirror of
				https://github.com/GayPizzaSpecifications/voxelotl-engine.git
				synced 2025-11-04 02:59:37 +00:00 
			
		
		
		
	fix memory leaks + minor refactor
This commit is contained in:
		@ -31,15 +31,15 @@ public class Application {
 | 
				
			|||||||
    if cfg.flags.contains(.highDPI) {
 | 
					    if cfg.flags.contains(.highDPI) {
 | 
				
			||||||
      windowFlags |= SDL_WindowFlags(SDL_WINDOW_HIGH_PIXEL_DENSITY)
 | 
					      windowFlags |= SDL_WindowFlags(SDL_WINDOW_HIGH_PIXEL_DENSITY)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    window = SDL_CreateWindow(cfg.title, cfg.width, cfg.height, windowFlags)
 | 
					    window = SDL_CreateWindow(cfg.title, cfg.frame.w, cfg.frame.h, windowFlags)
 | 
				
			||||||
    guard window != nil else {
 | 
					    guard window != nil else {
 | 
				
			||||||
      printErr("SDL_CreateWindow() error: \(String(cString: SDL_GetError()))")
 | 
					      printErr("SDL_CreateWindow() error: \(String(cString: SDL_GetError()))")
 | 
				
			||||||
      return .exitFailure
 | 
					      return .exitFailure
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Get window metrics
 | 
					    // Get window metrics
 | 
				
			||||||
    var backBufferWidth: Int32 = 0, backBufferHeight: Int32 = 0
 | 
					    var backBuffer = Size<Int32>.zero
 | 
				
			||||||
    guard SDL_GetWindowSizeInPixels(window, &backBufferWidth, &backBufferHeight) >= 0 else {
 | 
					    guard SDL_GetWindowSizeInPixels(window, &backBuffer.w, &backBuffer.h) >= 0 else {
 | 
				
			||||||
      printErr("SDL_GetWindowSizeInPixels() error: \(String(cString: SDL_GetError()))")
 | 
					      printErr("SDL_GetWindowSizeInPixels() error: \(String(cString: SDL_GetError()))")
 | 
				
			||||||
      return .exitFailure
 | 
					      return .exitFailure
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -49,7 +49,7 @@ public class Application {
 | 
				
			|||||||
    do {
 | 
					    do {
 | 
				
			||||||
      let layer = unsafeBitCast(SDL_Metal_GetLayer(view), to: CAMetalLayer.self)
 | 
					      let layer = unsafeBitCast(SDL_Metal_GetLayer(view), to: CAMetalLayer.self)
 | 
				
			||||||
      layer.displaySyncEnabled = cfg.vsyncMode == .off ? false : true
 | 
					      layer.displaySyncEnabled = cfg.vsyncMode == .off ? false : true
 | 
				
			||||||
      self.renderer = try Renderer(layer: layer, size: .init(Int(backBufferWidth), Int(backBufferHeight)))
 | 
					      self.renderer = try Renderer(layer: layer, size: Size<Int>(backBuffer))
 | 
				
			||||||
    } catch RendererError.initFailure(let message) {
 | 
					    } catch RendererError.initFailure(let message) {
 | 
				
			||||||
      printErr("Renderer init error: \(message)")
 | 
					      printErr("Renderer init error: \(message)")
 | 
				
			||||||
      return .exitFailure
 | 
					      return .exitFailure
 | 
				
			||||||
@ -122,9 +122,9 @@ public class Application {
 | 
				
			|||||||
    del.update(gameTime)
 | 
					    del.update(gameTime)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
      try renderer!.beginFrame()
 | 
					      try renderer!.newFrame {
 | 
				
			||||||
      del.draw(renderer!, gameTime)
 | 
					        del.draw($0, gameTime)
 | 
				
			||||||
      renderer!.endFrame()
 | 
					      }
 | 
				
			||||||
    } catch RendererError.drawFailure(let message) {
 | 
					    } catch RendererError.drawFailure(let message) {
 | 
				
			||||||
      printErr("Renderer draw error: \(message)")
 | 
					      printErr("Renderer draw error: \(message)")
 | 
				
			||||||
      return .exitFailure
 | 
					      return .exitFailure
 | 
				
			||||||
@ -182,15 +182,13 @@ public struct ApplicationConfiguration {
 | 
				
			|||||||
    case adaptive
 | 
					    case adaptive
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let width: Int32
 | 
					  let frame: Size<Int32>
 | 
				
			||||||
  let height: Int32
 | 
					 | 
				
			||||||
  let title: String
 | 
					  let title: String
 | 
				
			||||||
  let flags: Flags
 | 
					  let flags: Flags
 | 
				
			||||||
  let vsyncMode: VSyncMode
 | 
					  let vsyncMode: VSyncMode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public init(width: Int32, height: Int32, title: String, flags: Flags, vsyncMode: VSyncMode) {
 | 
					  public init(frame: Size<Int32>, title: String, flags: Flags, vsyncMode: VSyncMode) {
 | 
				
			||||||
    self.width = width
 | 
					    self.frame = frame
 | 
				
			||||||
    self.height = height
 | 
					 | 
				
			||||||
    self.title = title
 | 
					    self.title = title
 | 
				
			||||||
    self.flags = flags
 | 
					    self.flags = flags
 | 
				
			||||||
    self.vsyncMode = vsyncMode
 | 
					    self.vsyncMode = vsyncMode
 | 
				
			||||||
 | 
				
			|||||||
@ -42,6 +42,10 @@ public struct Size<T: AdditiveArithmetic>: Equatable {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
extension Size where T: BinaryInteger {
 | 
					extension Size where T: BinaryInteger {
 | 
				
			||||||
  static var one: Self { .init(T(1), T(1)) }
 | 
					  static var one: Self { .init(T(1), T(1)) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  init<O>(_ other: Size<O>) where O: BinaryInteger {
 | 
				
			||||||
 | 
					    self.init(T(other.w), T(other.h))
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Rect<T: AdditiveArithmetic>: Equatable {
 | 
					struct Rect<T: AdditiveArithmetic>: Equatable {
 | 
				
			||||||
 | 
				
			|||||||
@ -55,9 +55,7 @@ public class Renderer {
 | 
				
			|||||||
  private var depthStencilState: MTLDepthStencilState
 | 
					  private var depthStencilState: MTLDepthStencilState
 | 
				
			||||||
  private var depthTextures: [MTLTexture]
 | 
					  private var depthTextures: [MTLTexture]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private var _commandBuf: MTLCommandBuffer!
 | 
					  private var _encoder: MTLRenderCommandEncoder! = nil
 | 
				
			||||||
  private var _encoder: MTLRenderCommandEncoder!
 | 
					 | 
				
			||||||
  private var _rt: (any CAMetalDrawable)!
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private var vtxBuffer: MTLBuffer, idxBuffer: MTLBuffer
 | 
					  private var vtxBuffer: MTLBuffer, idxBuffer: MTLBuffer
 | 
				
			||||||
  private var defaultTexture: MTLTexture
 | 
					  private var defaultTexture: MTLTexture
 | 
				
			||||||
@ -201,71 +199,75 @@ public class Renderer {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static func loadTexture(_ device: MTLDevice, _ queue: MTLCommandQueue, image2D image: Image2D) throws -> MTLTexture {
 | 
					  static func loadTexture(_ device: MTLDevice, _ queue: MTLCommandQueue, image2D image: Image2D) throws -> MTLTexture {
 | 
				
			||||||
    let texDesc = MTLTextureDescriptor()
 | 
					    try autoreleasepool {
 | 
				
			||||||
    texDesc.width  = image.width
 | 
					      let texDesc = MTLTextureDescriptor()
 | 
				
			||||||
    texDesc.height = image.height
 | 
					      texDesc.width  = image.width
 | 
				
			||||||
    texDesc.pixelFormat = .rgba8Unorm_srgb
 | 
					      texDesc.height = image.height
 | 
				
			||||||
    texDesc.textureType = .type2D
 | 
					      texDesc.pixelFormat = .rgba8Unorm_srgb
 | 
				
			||||||
    texDesc.storageMode = .private
 | 
					      texDesc.textureType = .type2D
 | 
				
			||||||
    texDesc.usage = .shaderRead
 | 
					      texDesc.storageMode = .private
 | 
				
			||||||
    guard let newTexture = device.makeTexture(descriptor: texDesc) else {
 | 
					      texDesc.usage = .shaderRead
 | 
				
			||||||
      throw RendererError.loadFailure("Failed to create texture descriptor")
 | 
					      guard let newTexture = device.makeTexture(descriptor: texDesc) else {
 | 
				
			||||||
 | 
					        throw RendererError.loadFailure("Failed to create texture descriptor")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      guard let texData = image.data.withUnsafeBytes({ bytes in
 | 
				
			||||||
 | 
					        device.makeBuffer(bytes: bytes.baseAddress!, length: bytes.count, options: [ .storageModeShared ])
 | 
				
			||||||
 | 
					      }) else {
 | 
				
			||||||
 | 
					        throw RendererError.loadFailure("Failed to create shared texture data buffer")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      guard let cmdBuffer = queue.makeCommandBuffer(),
 | 
				
			||||||
 | 
					        let blitEncoder = cmdBuffer.makeBlitCommandEncoder()
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
 | 
					        throw RendererError.loadFailure("Failed to create blit command encoder")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      blitEncoder.copy(
 | 
				
			||||||
 | 
					        from: texData,
 | 
				
			||||||
 | 
					        sourceOffset: 0,
 | 
				
			||||||
 | 
					        sourceBytesPerRow: image.stride,
 | 
				
			||||||
 | 
					        sourceBytesPerImage: image.stride * image.height,
 | 
				
			||||||
 | 
					        sourceSize: .init(width: image.width, height: image.height, depth: 1),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        to: newTexture,
 | 
				
			||||||
 | 
					        destinationSlice: 0,
 | 
				
			||||||
 | 
					        destinationLevel: 0,
 | 
				
			||||||
 | 
					        destinationOrigin: .init(x: 0, y: 0, z: 0))
 | 
				
			||||||
 | 
					      blitEncoder.endEncoding()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      cmdBuffer.addCompletedHandler { _ in
 | 
				
			||||||
 | 
					        //FIXME: look into if this needs to be synchronised
 | 
				
			||||||
 | 
					        //printErr("Texture was added?")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      cmdBuffer.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return newTexture
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    guard let texData = image.data.withUnsafeBytes({ bytes in
 | 
					 | 
				
			||||||
      device.makeBuffer(bytes: bytes.baseAddress!, length: bytes.count, options: [ .storageModeShared ])
 | 
					 | 
				
			||||||
    }) else {
 | 
					 | 
				
			||||||
      throw RendererError.loadFailure("Failed to create shared texture data buffer")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    guard let cmdBuffer = queue.makeCommandBuffer(),
 | 
					 | 
				
			||||||
      let blitEncoder = cmdBuffer.makeBlitCommandEncoder()
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
      throw RendererError.loadFailure("Failed to create blit command encoder")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    blitEncoder.copy(
 | 
					 | 
				
			||||||
      from: texData,
 | 
					 | 
				
			||||||
      sourceOffset: 0,
 | 
					 | 
				
			||||||
      sourceBytesPerRow: image.stride,
 | 
					 | 
				
			||||||
      sourceBytesPerImage: image.stride * image.height,
 | 
					 | 
				
			||||||
      sourceSize: .init(width: image.width, height: image.height, depth: 1),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      to: newTexture,
 | 
					 | 
				
			||||||
      destinationSlice: 0,
 | 
					 | 
				
			||||||
      destinationLevel: 0,
 | 
					 | 
				
			||||||
      destinationOrigin: .init(x: 0, y: 0, z: 0))
 | 
					 | 
				
			||||||
    blitEncoder.endEncoding()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cmdBuffer.addCompletedHandler { _ in
 | 
					 | 
				
			||||||
      //FIXME: look into if this needs to be synchronised
 | 
					 | 
				
			||||||
      //printErr("Texture was added?")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    cmdBuffer.commit()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return newTexture
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private static func createDepthTexture(_ device: MTLDevice, _ size: Size<Int>, format: MTLPixelFormat
 | 
					  private static func createDepthTexture(_ device: MTLDevice, _ size: Size<Int>, format: MTLPixelFormat
 | 
				
			||||||
  ) -> MTLTexture? {
 | 
					  ) -> MTLTexture? {
 | 
				
			||||||
    let texDescriptor = MTLTextureDescriptor.texture2DDescriptor(
 | 
					    autoreleasepool {
 | 
				
			||||||
      pixelFormat: format,
 | 
					      let texDescriptor = MTLTextureDescriptor.texture2DDescriptor(
 | 
				
			||||||
      width:       size.w,
 | 
					        pixelFormat: format,
 | 
				
			||||||
      height:      size.h,
 | 
					        width:       size.w,
 | 
				
			||||||
      mipmapped:   false)
 | 
					        height:      size.h,
 | 
				
			||||||
    texDescriptor.depth = 1
 | 
					        mipmapped:   false)
 | 
				
			||||||
    texDescriptor.sampleCount = 1
 | 
					      texDescriptor.depth = 1
 | 
				
			||||||
    texDescriptor.usage       = [ .renderTarget, .shaderRead ]
 | 
					      texDescriptor.sampleCount = 1
 | 
				
			||||||
#if !NDEBUG
 | 
					      texDescriptor.usage       = [ .renderTarget, .shaderRead ]
 | 
				
			||||||
    texDescriptor.storageMode = .private
 | 
					  #if !NDEBUG
 | 
				
			||||||
#else
 | 
					      texDescriptor.storageMode = .private
 | 
				
			||||||
    texDescriptor.storageMode = .memoryless
 | 
					  #else
 | 
				
			||||||
#endif
 | 
					      texDescriptor.storageMode = .memoryless
 | 
				
			||||||
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    guard let depthStencilTexture = device.makeTexture(descriptor: texDescriptor) else { return nil }
 | 
					      guard let depthStencilTexture = device.makeTexture(descriptor: texDescriptor) else { return nil }
 | 
				
			||||||
    depthStencilTexture.label = "Depth buffer"
 | 
					      depthStencilTexture.label = "Depth buffer"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return depthStencilTexture
 | 
					      return depthStencilTexture
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static func makeViewport(rect: Rect<Int>, znear: Double = 0.0, zfar: Double = 1.0) -> MTLViewport {
 | 
					  static func makeViewport(rect: Rect<Int>, znear: Double = 0.0, zfar: Double = 1.0) -> MTLViewport {
 | 
				
			||||||
@ -288,41 +290,56 @@ public class Renderer {
 | 
				
			|||||||
    self._aspectRatio = Float(self.backBufferSize.w) / Float(self.backBufferSize.h)
 | 
					    self._aspectRatio = Float(self.backBufferSize.w) / Float(self.backBufferSize.h)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  func beginFrame() throws {
 | 
					  func newFrame(_ frameFunc: (Renderer) -> Void) throws {
 | 
				
			||||||
    // Lock the semaphore here if too many frames are "in flight"
 | 
					    try autoreleasepool {
 | 
				
			||||||
    _ = inFlightSemaphore.wait(timeout: .distantFuture)
 | 
					      guard let rt = layer.nextDrawable() else {
 | 
				
			||||||
 | 
					        throw RendererError.drawFailure("Failed to get next drawable render target")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    guard let rt = layer.nextDrawable() else {
 | 
					      passDescription.colorAttachments[0].texture = rt.texture
 | 
				
			||||||
      throw RendererError.drawFailure("Failed to get next drawable render target")
 | 
					      passDescription.depthAttachment.texture = self.depthTextures[self.currentFrame]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Lock the semaphore here if too many frames are "in flight"
 | 
				
			||||||
 | 
					      _ = inFlightSemaphore.wait(timeout: .distantFuture)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      guard let commandBuf: MTLCommandBuffer = queue.makeCommandBuffer() else {
 | 
				
			||||||
 | 
					        throw RendererError.drawFailure("Failed to make command buffer from queue")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      commandBuf.addCompletedHandler { _ in
 | 
				
			||||||
 | 
					        self.inFlightSemaphore.signal()
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      guard let encoder = commandBuf.makeRenderCommandEncoder(descriptor: passDescription) else {
 | 
				
			||||||
 | 
					        throw RendererError.drawFailure("Failed to make render encoder from command buffer")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      encoder.setCullMode(.back)
 | 
				
			||||||
 | 
					      encoder.setFrontFacing(.counterClockwise)  // OpenGL default
 | 
				
			||||||
 | 
					      encoder.setViewport(Self.makeViewport(rect: self.frame))
 | 
				
			||||||
 | 
					      encoder.setRenderPipelineState(pso)
 | 
				
			||||||
 | 
					      encoder.setDepthStencilState(depthStencilState)
 | 
				
			||||||
 | 
					      encoder.setFragmentTexture(cubeTexture ?? defaultTexture, index: 0)
 | 
				
			||||||
 | 
					      encoder.setVertexBuffer(vtxBuffer,
 | 
				
			||||||
 | 
					        offset: 0,
 | 
				
			||||||
 | 
					        index: ShaderInputIdx.vertices.rawValue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      self._encoder = encoder
 | 
				
			||||||
 | 
					      frameFunc(self)
 | 
				
			||||||
 | 
					      self._encoder = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      encoder.endEncoding()
 | 
				
			||||||
 | 
					      commandBuf.present(rt)
 | 
				
			||||||
 | 
					      commandBuf.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      self.currentFrame &+= 1
 | 
				
			||||||
 | 
					      if self.currentFrame == numFramesInFlight {
 | 
				
			||||||
 | 
					        self.currentFrame = 0
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    self._rt = rt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    passDescription.colorAttachments[0].texture = self._rt.texture
 | 
					 | 
				
			||||||
    passDescription.depthAttachment.texture = self.depthTextures[self.currentFrame]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    guard let commandBuf: MTLCommandBuffer = queue.makeCommandBuffer() else {
 | 
					 | 
				
			||||||
      throw RendererError.drawFailure("Failed to make command buffer from queue")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    self._commandBuf = commandBuf
 | 
					 | 
				
			||||||
    self._commandBuf.addCompletedHandler { _ in
 | 
					 | 
				
			||||||
      self.inFlightSemaphore.signal()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    guard let encoder = self._commandBuf.makeRenderCommandEncoder(descriptor: passDescription) else {
 | 
					 | 
				
			||||||
      throw RendererError.drawFailure("Failed to make render encoder from command buffer")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    self._encoder = encoder
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    self._encoder.setCullMode(.back)
 | 
					 | 
				
			||||||
    self._encoder.setFrontFacing(.counterClockwise)  // OpenGL default
 | 
					 | 
				
			||||||
    self._encoder.setViewport(Self.makeViewport(rect: self.frame))
 | 
					 | 
				
			||||||
    self._encoder.setRenderPipelineState(pso)
 | 
					 | 
				
			||||||
    self._encoder.setDepthStencilState(depthStencilState)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    self._encoder.setFragmentTexture(cubeTexture ?? defaultTexture, index: 0)
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  func batch(instances: [Instance], camera: Camera) {
 | 
					  func batch(instances: [Instance], camera: Camera) {
 | 
				
			||||||
 | 
					    assert(self._encoder != nil, "batch can't be called outside of a frame being rendered")
 | 
				
			||||||
    assert(instances.count < 52)
 | 
					    assert(instances.count < 52)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var uniforms = ShaderUniforms(projView: camera.viewProjection)
 | 
					    var uniforms = ShaderUniforms(projView: camera.viewProjection)
 | 
				
			||||||
@ -339,10 +356,6 @@ public class Renderer {
 | 
				
			|||||||
          UInt8(instance.color.w * 0xFF)))
 | 
					          UInt8(instance.color.w * 0xFF)))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self._encoder.setVertexBuffer(vtxBuffer,
 | 
					 | 
				
			||||||
      offset: 0,
 | 
					 | 
				
			||||||
      index: ShaderInputIdx.vertices.rawValue)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Ideal as long as our uniforms total 4 KB or less
 | 
					    // Ideal as long as our uniforms total 4 KB or less
 | 
				
			||||||
    self._encoder.setVertexBytes(instances,
 | 
					    self._encoder.setVertexBytes(instances,
 | 
				
			||||||
      length: instances.count * MemoryLayout<ShaderInstance>.stride,
 | 
					      length: instances.count * MemoryLayout<ShaderInstance>.stride,
 | 
				
			||||||
@ -359,21 +372,6 @@ public class Renderer {
 | 
				
			|||||||
      indexBufferOffset: 0,
 | 
					      indexBufferOffset: 0,
 | 
				
			||||||
      instanceCount: instances.count)
 | 
					      instanceCount: instances.count)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  func endFrame() {
 | 
					 | 
				
			||||||
    self._encoder.endEncoding()
 | 
					 | 
				
			||||||
    self._commandBuf.present(self._rt)
 | 
					 | 
				
			||||||
    self._commandBuf.commit()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    self._rt = nil
 | 
					 | 
				
			||||||
    self._encoder = nil
 | 
					 | 
				
			||||||
    self._commandBuf = nil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    self.currentFrame &+= 1
 | 
					 | 
				
			||||||
    if self.currentFrame == numFramesInFlight {
 | 
					 | 
				
			||||||
      self.currentFrame = 0
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum RendererError: Error {
 | 
					enum RendererError: Error {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,9 @@
 | 
				
			|||||||
import Darwin
 | 
					import Darwin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var rect = Rect(origin: .init(0, 0), size: .init(32, 32))
 | 
					 | 
				
			||||||
rect.origin += Point(10, 10)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let app = Application(
 | 
					let app = Application(
 | 
				
			||||||
  delegate: Game(),
 | 
					  delegate: Game(),
 | 
				
			||||||
  configuration: ApplicationConfiguration(
 | 
					  configuration: ApplicationConfiguration(
 | 
				
			||||||
  width: 1280,
 | 
					  frame: Size(1280, 720),
 | 
				
			||||||
  height: 720,
 | 
					 | 
				
			||||||
  title: "Voxelotl Demo",
 | 
					  title: "Voxelotl Demo",
 | 
				
			||||||
  flags: [ .resizable, .highDPI ],
 | 
					  flags: [ .resizable, .highDPI ],
 | 
				
			||||||
  vsyncMode: .on(interval: 1)))
 | 
					  vsyncMode: .on(interval: 1)))
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user