Skip to content

Instantly share code, notes, and snippets.

@nbhasin2
Last active April 2, 2025 06:50
Show Gist options
  • Save nbhasin2/a988a2ec20763b018fd641136fe9505a to your computer and use it in GitHub Desktop.
Save nbhasin2/a988a2ec20763b018fd641136fe9505a to your computer and use it in GitHub Desktop.
Renderer_Step4.swift
import MetalKit
import SwiftUI
class Renderer: NSObject, MTKViewDelegate {
var device: MTLDevice!
var commandQueue: MTLCommandQueue!
var pipelineState: MTLRenderPipelineState!
var time: Float = 0.0
init(device: MTLDevice) {
super.init()
self.device = device
self.commandQueue = device.makeCommandQueue()
self.setupPipeline()
}
func setupPipeline() {
let library = device.makeDefaultLibrary()
let vertexFunction = library?.makeFunction(name: "circle_vertex")
let fragmentFunction = library?.makeFunction(name: "circle_fragment")
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.vertexFunction = vertexFunction
pipelineDescriptor.fragmentFunction = fragmentFunction
pipelineDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm
do {
pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
} catch {
fatalError("Failed to create pipeline state")
}
}
func draw(in view: MTKView) {
guard let drawable = view.currentDrawable else { return }
guard let descriptor = view.currentRenderPassDescriptor else { return }
let commandBuffer = commandQueue.makeCommandBuffer()!
let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor)!
commandEncoder.setRenderPipelineState(pipelineState)
commandEncoder.setFragmentBytes(&time, length: MemoryLayout<Float>.size, index: 0)
commandEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
commandEncoder.endEncoding()
commandBuffer.present(drawable)
commandBuffer.commit()
time += 0.01
}
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {}
}
struct MetalView: UIViewRepresentable {
var device: MTLDevice
func makeUIView(context: Context) -> MTKView {
let view = MTKView()
view.device = device
view.colorPixelFormat = .bgra8Unorm
view.framebufferOnly = false
let renderer = Renderer(device: device)
view.delegate = renderer
context.coordinator.renderer = renderer
return view
}
func updateUIView(_ uiView: MTKView, context: Context) {}
func makeCoordinator() -> Coordinator {
Coordinator()
}
class Coordinator {
var renderer: Renderer?
}
}
struct ContentView: View {
var body: some View {
MetalView(device: MTLCreateSystemDefaultDevice()!)
.edgesIgnoringSafeArea(.all)
}
}
#Preview {
ContentView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment