-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bugfix/multi buffers #653
Bugfix/multi buffers #653
Changes from all commits
ceed142
6e07e74
c99fbb6
90ba6ac
5f88de5
4e5d0be
5381563
e9a09ff
9570689
9c0d86d
2ec143d
e96bcbb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -69,9 +69,12 @@ final class Icosahedron: BaseGraphicsObject, @unchecked Sendable { | |||||||||||||||||||||||||||
shader.preRender(context) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
encoder.setVertexBuffer(verticesBuffer, offset: 0, index: 0) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
let vpMatrixBuffer = vpMatrixBuffers.getNextBuffer(context) | ||||||||||||||||||||||||||||
if let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)) { | ||||||||||||||||||||||||||||
encoder.setVertexBytes(matrixPointer, length: 64, index: 1) | ||||||||||||||||||||||||||||
vpMatrixBuffer?.contents().copyMemory(from: matrixPointer, byteCount: 64) | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
encoder.setVertexBuffer(vpMatrixBuffer, offset: 0, index: 1) | ||||||||||||||||||||||||||||
Comment on lines
+72
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add null check before accessing vpMatrixBuffer contents. The buffer management change from Consider adding a null check: let vpMatrixBuffer = vpMatrixBuffers.getNextBuffer(context)
-if let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)) {
+if let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)),
+ let buffer = vpMatrixBuffer {
- vpMatrixBuffer?.contents().copyMemory(from: matrixPointer, byteCount: 64)
+ buffer.contents().copyMemory(from: matrixPointer, byteCount: 64)
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
encoder.drawIndexedPrimitives(type: .triangle, | ||||||||||||||||||||||||||||
indexCount: indicesCount, | ||||||||||||||||||||||||||||
|
@@ -120,9 +123,12 @@ extension Icosahedron: MCMaskingObjectInterface { | |||||||||||||||||||||||||||
shader.preRender(context) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
encoder.setVertexBuffer(verticesBuffer, offset: 0, index: 0) | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
let vpMatrixBuffer = vpMatrixBuffers.getNextBuffer(context) | ||||||||||||||||||||||||||||
if let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)) { | ||||||||||||||||||||||||||||
encoder.setVertexBytes(matrixPointer, length: 64, index: 1) | ||||||||||||||||||||||||||||
vpMatrixBuffer?.contents().copyMemory(from: matrixPointer, byteCount: 64) | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
encoder.setVertexBuffer(vpMatrixBuffer, offset: 0, index: 1) | ||||||||||||||||||||||||||||
Comment on lines
+127
to
+131
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Extract duplicated matrix buffer logic into a helper method. This code block is identical to the one in the first render method. Consider extracting it to reduce duplication and centralize the safety improvements. Create a private helper method: private func setupVPMatrixBuffer(_ vpMatrix: Int64, context: RenderingContext, encoder: MTLRenderCommandEncoder) {
guard let vpMatrixBuffer = vpMatrixBuffers.getNextBuffer(context),
let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)) else {
return
}
vpMatrixBuffer.contents().copyMemory(from: matrixPointer, byteCount: 64)
encoder.setVertexBuffer(vpMatrixBuffer, offset: 0, index: 1)
} Then use it in both render methods: -let vpMatrixBuffer = vpMatrixBuffers.getNextBuffer(context)
-if let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)) {
- vpMatrixBuffer?.contents().copyMemory(from: matrixPointer, byteCount: 64)
-}
-encoder.setVertexBuffer(vpMatrixBuffer, offset: 0, index: 1)
+setupVPMatrixBuffer(vpMatrix, context: context, encoder: encoder) |
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
encoder.drawIndexedPrimitives(type: .triangle, | ||||||||||||||||||||||||||||
indexCount: indicesCount, | ||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -36,6 +36,7 @@ final class LineGroup2d: BaseGraphicsObject, @unchecked Sendable { | |||||||||||||||||||||||||||||||||||||||||||||||||||
label: "LineGroup2d") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
var originOffset: simd_float4 = simd_float4(0, 0, 0, 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
tileOriginBuffer = metalContext.device.makeBuffer(bytes: &originOffset, length: MemoryLayout<simd_float4>.stride, options: []) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
private func setupStencilBufferDescriptor() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -115,10 +116,13 @@ final class LineGroup2d: BaseGraphicsObject, @unchecked Sendable { | |||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
encoder.setVertexBuffer(lineVerticesBuffer, offset: 0, index: 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
let vpMatrixBuffer = vpMatrixBuffers.getNextBuffer(context) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
if let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
encoder.setVertexBytes(matrixPointer, length: 64, index: 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
vpMatrixBuffer?.contents().copyMemory(from: matrixPointer, byteCount: 64) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
encoder.setVertexBuffer(vpMatrixBuffer, offset: 0, index: 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+119
to
+123
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null check for vpMatrixBuffer before memory copy. While the switch to buffer-based matrix handling is good, the code should verify that let vpMatrixBuffer = vpMatrixBuffers.getNextBuffer(context)
-if let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)) {
+guard let vpMatrixBuffer, let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)) else {
+ return
+}
- vpMatrixBuffer?.contents().copyMemory(from: matrixPointer, byteCount: 64)
+vpMatrixBuffer.contents().copyMemory(from: matrixPointer, byteCount: 64) 📝 Committable suggestion
Suggested change
Comment on lines
+119
to
+123
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null check before copying memory to vpMatrixBuffer. While the buffer pool pattern is a good improvement for thread safety, the code should verify that Consider this safer implementation: let vpMatrixBuffer = vpMatrixBuffers.getNextBuffer(context)
-if let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)) {
+guard let vpMatrixBuffer = vpMatrixBuffer,
+ let matrixPointer = UnsafeRawPointer(bitPattern: Int(vpMatrix)) else {
+ return
+}
- vpMatrixBuffer?.contents().copyMemory(from: matrixPointer, byteCount: 64)
+vpMatrixBuffer.contents().copyMemory(from: matrixPointer, byteCount: 64) 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
let originOffsetBuffer = originOffsetBuffers.getNextBuffer(context) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
if let bufferPointer = originOffsetBuffer?.contents().assumingMemoryBound(to: simd_float4.self) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
bufferPointer.pointee.x = Float(originOffset.x - origin.x) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
bufferPointer.pointee.y = Float(originOffset.y - origin.y) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -158,6 +162,9 @@ extension LineGroup2d: MCLineGroup2dInterface { | |||||||||||||||||||||||||||||||||||||||||||||||||||
bufferPointer.pointee.y = originOffset.yF | ||||||||||||||||||||||||||||||||||||||||||||||||||||
bufferPointer.pointee.z = originOffset.zF | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
fatalError() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+165
to
+167
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Improve error handling for buffer access failure. The current implementation uses Consider these improvements: -else {
- fatalError()
-}
+else {
+ NSLog("Failed to access tileOriginBuffer contents in LineGroup2d.setLines")
+ // Reset state to prevent undefined behavior
+ self.lineVerticesBuffer = nil
+ self.lineIndicesBuffer = nil
+ self.indicesCount = 0
+ return
+} 📝 Committable suggestion
Suggested change
Comment on lines
+165
to
+167
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace fatal error with graceful error handling. Using Consider this alternative approach: -else {
- fatalError()
-}
+else {
+ NSLog("Failed to access tileOriginBuffer in LineGroup2d")
+ return
+} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
self.lineVerticesBuffer.copyOrCreate(from: lines, device: device) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
self.lineIndicesBuffer.copyOrCreate(from: indices, device: device) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
if self.lineVerticesBuffer != nil, self.lineIndicesBuffer != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// | ||
// MultiBuffer.swift | ||
// MapCore | ||
// | ||
// Created by Nicolas Märki on 04.11.2024. | ||
// | ||
|
||
import Metal | ||
import simd | ||
|
||
public struct MultiBuffer<DataType> { | ||
// Warning: Seems like suited to be generic | ||
// But makeBuffer &reference does not like generic data | ||
var buffers: [MTLBuffer] | ||
|
||
fileprivate init(buffers: [MTLBuffer]) { | ||
self.buffers = buffers | ||
} | ||
|
||
public mutating func getNextBuffer(_ context: RenderingContext) | ||
-> MTLBuffer? | ||
{ | ||
return buffers[context.currentBufferIndex] | ||
} | ||
} | ||
|
||
extension MultiBuffer<simd_float1> { | ||
public init(device: MTLDevice) { | ||
var initialMutable = simd_float1(1.0) | ||
let buffers: [MTLBuffer] = (0..<RenderingContext.bufferCount).compactMap | ||
{ _ in | ||
device | ||
.makeBuffer( | ||
bytes: &initialMutable, | ||
length: MemoryLayout<simd_float1>.stride | ||
) | ||
} | ||
self.init(buffers: buffers) | ||
} | ||
} | ||
|
||
extension MultiBuffer<simd_float4> { | ||
public init(device: MTLDevice) { | ||
var initialMutable = simd_float4(0.0, 0.0, 0.0, 0.0) | ||
let buffers: [MTLBuffer] = (0..<RenderingContext.bufferCount).compactMap | ||
{ _ in | ||
device | ||
.makeBuffer( | ||
bytes: &initialMutable, | ||
length: MemoryLayout<simd_float4>.stride | ||
) | ||
} | ||
self.init(buffers: buffers) | ||
} | ||
} | ||
|
||
extension MultiBuffer<simd_float4x4> { | ||
public init(device: MTLDevice) { | ||
var initialMutable = simd_float4x4(1.0) | ||
let buffers: [MTLBuffer] = (0..<RenderingContext.bufferCount).compactMap | ||
{ _ in | ||
device | ||
.makeBuffer( | ||
bytes: &initialMutable, | ||
length: MemoryLayout<simd_float4x4>.stride | ||
) | ||
} | ||
self.init(buffers: buffers) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add safety checks for buffer and pointer operations.
The current implementation has potential safety issues:
vpMatrixBuffer
before useUnsafeRawPointer
Consider applying this safer implementation:
📝 Committable suggestion