Factor out per-frame stuff into a PerFrameObject<T> class; use it for the rendering Uniforms
This commit is contained in:
parent
65ffec18e9
commit
907a0845a7
2 changed files with 40 additions and 35 deletions
|
@ -30,7 +30,6 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
public let device: MTLDevice
|
||||
let library: MTLLibrary
|
||||
let commandQueue: MTLCommandQueue
|
||||
var dynamicUniformBuffer: MTLBuffer
|
||||
var pipelineState: MTLRenderPipelineState
|
||||
var normalPipelineState: MTLRenderPipelineState
|
||||
var depthState: MTLDepthStencilState
|
||||
|
@ -38,9 +37,7 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
let inFlightSemaphore = DispatchSemaphore(value: maxBuffersInFlight)
|
||||
let regenerationSemaphore = DispatchSemaphore(value: 1)
|
||||
|
||||
var uniformBufferOffset = 0
|
||||
var uniformBufferIndex = 0
|
||||
var uniforms: UnsafeMutablePointer<Uniforms>
|
||||
var uniforms: PerFrameObject<Uniforms>
|
||||
|
||||
var lightsBuffer: MTLBuffer
|
||||
var lights: UnsafeMutablePointer<Light>
|
||||
|
@ -71,14 +68,7 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
self.device = metalKitView.device!
|
||||
self.commandQueue = self.device.makeCommandQueue()!
|
||||
|
||||
let uniformBufferSize = alignedUniformsSize * maxBuffersInFlight
|
||||
|
||||
self.dynamicUniformBuffer = self.device.makeBuffer(length:uniformBufferSize,
|
||||
options:[MTLResourceOptions.storageModeShared])!
|
||||
|
||||
self.dynamicUniformBuffer.label = "UniformBuffer"
|
||||
|
||||
uniforms = UnsafeMutableRawPointer(dynamicUniformBuffer.contents()).bindMemory(to:Uniforms.self, capacity:1)
|
||||
uniforms = PerFrameObject(device: device, label: "Uniforms")
|
||||
|
||||
metalKitView.depthStencilPixelFormat = MTLPixelFormat.depth32Float_stencil8
|
||||
metalKitView.colorPixelFormat = MTLPixelFormat.bgra8Unorm_srgb
|
||||
|
@ -199,16 +189,6 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
material[0].specularExponent = 10
|
||||
}
|
||||
|
||||
private func updateDynamicBufferState() {
|
||||
/// Update the state of our uniform buffers before rendering
|
||||
|
||||
uniformBufferIndex = (uniformBufferIndex + 1) % maxBuffersInFlight
|
||||
|
||||
uniformBufferOffset = alignedUniformsSize * uniformBufferIndex
|
||||
|
||||
uniforms = UnsafeMutableRawPointer(dynamicUniformBuffer.contents() + uniformBufferOffset).bindMemory(to:Uniforms.self, capacity:1)
|
||||
}
|
||||
|
||||
private func updateGameState() {
|
||||
/// Update any game state before rendering
|
||||
if iterateTerrainAlgorithm {
|
||||
|
@ -217,21 +197,21 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
uniforms[0].projectionMatrix = projectionMatrix
|
||||
uniforms.pointer[0].projectionMatrix = projectionMatrix
|
||||
|
||||
let rotationAxis = float3(0, 1, 0)
|
||||
let modelMatrix = matrix4x4_rotation(radians: rotation, axis: rotationAxis)
|
||||
let viewMatrix = matrix4x4_translation(0.0, -2.0, -8.0)
|
||||
let modelViewMatrix = simd_mul(viewMatrix, modelMatrix)
|
||||
uniforms[0].modelViewMatrix = modelViewMatrix
|
||||
uniforms.pointer[0].modelViewMatrix = modelViewMatrix
|
||||
rotation += 0.003
|
||||
|
||||
// Remove the fourth row and column from our model-view matrix. Since we're only doing rotations and translations (no scales), this serves as our normal transform matrix.
|
||||
let rotSclModelViewMatrix = float3x3(modelViewMatrix.columns.0.xyz, modelViewMatrix.columns.1.xyz, modelViewMatrix.columns.2.xyz)
|
||||
uniforms[0].normalMatrix = rotSclModelViewMatrix
|
||||
uniforms.pointer[0].normalMatrix = rotSclModelViewMatrix
|
||||
|
||||
uniforms[0].terrainDimensions = terrain.dimensions
|
||||
uniforms[0].terrainSegments = terrain.segments
|
||||
uniforms.pointer[0].terrainDimensions = terrain.dimensions
|
||||
uniforms.pointer[0].terrainSegments = terrain.segments
|
||||
}
|
||||
|
||||
func draw(in view: MTKView) {
|
||||
|
@ -256,7 +236,7 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
inFlightSem.signal()
|
||||
}
|
||||
|
||||
self.updateDynamicBufferState()
|
||||
uniforms.updateOffsets()
|
||||
|
||||
self.updateGameState()
|
||||
|
||||
|
@ -270,7 +250,7 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
didScheduleAlgorithmIteration = true
|
||||
}
|
||||
|
||||
terrain.scheduleGeometryUpdates(inCommandBuffer: commandBuffer, uniforms: dynamicUniformBuffer, uniformsOffset: uniformBufferOffset)
|
||||
terrain.scheduleGeometryUpdates(inCommandBuffer: commandBuffer, uniforms: uniforms)
|
||||
|
||||
/// Delay getting the currentRenderPassDescriptor until we absolutely need it to avoid
|
||||
/// holding onto the drawable and blocking the display pipeline any longer than necessary
|
||||
|
@ -293,8 +273,8 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
renderEncoder.setTriangleFillMode(drawLines ? .lines : .fill)
|
||||
|
||||
renderEncoder.setVertexBuffer(terrain.faceNormalsBuffer, offset: 0, index: BufferIndex.faceNormals.rawValue)
|
||||
renderEncoder.setVertexBuffer(dynamicUniformBuffer, offset:uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
|
||||
renderEncoder.setFragmentBuffer(dynamicUniformBuffer, offset:uniformBufferOffset, index: BufferIndex.uniforms.rawValue)
|
||||
renderEncoder.setVertexBuffer(uniforms.buffer, offset: uniforms.offset, index: BufferIndex.uniforms.rawValue)
|
||||
renderEncoder.setFragmentBuffer(uniforms.buffer, offset: uniforms.offset, index: BufferIndex.uniforms.rawValue)
|
||||
|
||||
renderEncoder.setFragmentBuffer(lightsBuffer, offset: 0, index: BufferIndex.lights.rawValue)
|
||||
renderEncoder.setFragmentBuffer(materialBuffer, offset: 0, index: BufferIndex.materials.rawValue)
|
||||
|
@ -366,7 +346,7 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
|
||||
encoder.setVertexBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: NormalBufferIndex.points.rawValue)
|
||||
encoder.setVertexBuffer(normalBuffer.buffer, offset: normalBuffer.offset, index: NormalBufferIndex.normals.rawValue)
|
||||
encoder.setVertexBuffer(dynamicUniformBuffer, offset: uniformBufferOffset, index: NormalBufferIndex.uniforms.rawValue)
|
||||
encoder.setVertexBuffer(uniforms.buffer, offset: uniforms.offset, index: NormalBufferIndex.uniforms.rawValue)
|
||||
encoder.drawPrimitives(type: .line, vertexStart: 0, vertexCount: 2, instanceCount: terrain.mesh.vertexCount)
|
||||
|
||||
encoder.popDebugGroup()
|
||||
|
@ -381,9 +361,34 @@ class Renderer: NSObject, MTKViewDelegate {
|
|||
|
||||
encoder.setVertexBuffer(faceMidpointsBuffer, offset: 0, index: NormalBufferIndex.points.rawValue)
|
||||
encoder.setVertexBuffer(faceNormalsBuffer, offset: 0, index: NormalBufferIndex.normals.rawValue)
|
||||
encoder.setVertexBuffer(dynamicUniformBuffer, offset:uniformBufferOffset, index: NormalBufferIndex.uniforms.rawValue)
|
||||
encoder.setVertexBuffer(uniforms.buffer, offset: uniforms.offset, index: NormalBufferIndex.uniforms.rawValue)
|
||||
encoder.drawPrimitives(type: .line, vertexStart: 0, vertexCount: 2, instanceCount: instanceCount)
|
||||
|
||||
encoder.popDebugGroup()
|
||||
}
|
||||
}
|
||||
|
||||
struct PerFrameObject<T> {
|
||||
static var objectSize: Int {
|
||||
return (MemoryLayout<T>.size & ~0xFF) + 0x100
|
||||
}
|
||||
|
||||
private(set) var offset: Int = 0
|
||||
private(set) var index: Int = 0
|
||||
private(set) var buffer: MTLBuffer
|
||||
private(set) var pointer: UnsafeMutablePointer<T>
|
||||
|
||||
init(device: MTLDevice, label: String? = nil) {
|
||||
let bufferSize = PerFrameObject<T>.objectSize * maxBuffersInFlight
|
||||
|
||||
buffer = device.makeBuffer(length: bufferSize, options: .storageModeShared)!
|
||||
buffer.label = label
|
||||
pointer = UnsafeMutableRawPointer(buffer.contents()).bindMemory(to: T.self, capacity: 1)
|
||||
}
|
||||
|
||||
mutating func updateOffsets() {
|
||||
index = (index + 1) % maxBuffersInFlight
|
||||
offset = PerFrameObject<T>.objectSize * index
|
||||
pointer = UnsafeMutableRawPointer(buffer.contents() + offset).bindMemory(to: T.self, capacity: 1)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ class Terrain: NSObject {
|
|||
return progress
|
||||
}
|
||||
|
||||
func scheduleGeometryUpdates(inCommandBuffer commandBuffer: MTLCommandBuffer, uniforms: MTLBuffer, uniformsOffset: Int) {
|
||||
func scheduleGeometryUpdates(inCommandBuffer commandBuffer: MTLCommandBuffer, uniforms: PerFrameObject<Uniforms>) {
|
||||
if let computeEncoder = commandBuffer.makeComputeCommandEncoder() {
|
||||
//print("Scheduling update geometry heights")
|
||||
computeEncoder.label = "Geometry Heights Encoder"
|
||||
|
@ -165,7 +165,7 @@ class Terrain: NSObject {
|
|||
computeEncoder.setBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: GeneratorBufferIndex.meshPositions.rawValue)
|
||||
let texCoordBuffer = mesh.vertexBuffers[BufferIndex.meshGenerics.rawValue]
|
||||
computeEncoder.setBuffer(texCoordBuffer.buffer, offset: texCoordBuffer.offset, index: GeneratorBufferIndex.texCoords.rawValue)
|
||||
computeEncoder.setBuffer(uniforms, offset: uniformsOffset, index: GeneratorBufferIndex.uniforms.rawValue)
|
||||
computeEncoder.setBuffer(uniforms.buffer, offset: uniforms.offset, index: GeneratorBufferIndex.uniforms.rawValue)
|
||||
computeEncoder.dispatchThreads(MTLSize(width: Int(segments.x + 1), height: Int(segments.y + 1), depth: 1), threadsPerThreadgroup: MTLSize(width: 8, height: 8, depth: 1))
|
||||
computeEncoder.popDebugGroup()
|
||||
computeEncoder.endEncoding()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue