瀏覽代碼

Merge pull request #873 from floooh/issue872-metal-validation-error

sokol_gfx.h mtl: new attempt to fix swapchain lifetime issues
Andre Weissflog 2 年之前
父節點
當前提交
32de1ef01d
共有 3 個文件被更改,包括 22 次插入17 次删除
  1. 8 6
      .github/workflows/gen_bindings.yml
  2. 6 0
      CHANGELOG.md
  3. 8 11
      sokol_gfx.h

+ 8 - 6
.github/workflows/gen_bindings.yml

@@ -150,7 +150,9 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        os: [ubuntu-latest, macos-latest, windows-latest]
+        # FIXME: macOS Odin vs Homebrew LLVM currently seems broken
+        # os: [ubuntu-latest, macos-latest, windows-latest]
+        os: [ubuntu-latest, windows-latest]
     runs-on: ${{matrix.os}}
     steps:
       - uses: actions/checkout@v3
@@ -165,16 +167,16 @@ jobs:
         name: prepare-linux
         run: |
           sudo apt-get update
-          sudo apt-get install libglu1-mesa-dev mesa-common-dev xorg-dev libasound-dev llvm-11
-          curl -L https://github.com/odin-lang/Odin/releases/download/dev-2023-07/odin-ubuntu-amd64-dev-2023-07.zip --output odin.zip
+          sudo apt-get install libglu1-mesa-dev mesa-common-dev xorg-dev libasound-dev llvm-14
+          curl -L https://github.com/odin-lang/Odin/releases/download/dev-2023-08/odin-ubuntu-amd64-dev-2023-08.zip --output odin.zip
           unzip odin.zip
           chmod a+x ./odin
           ./build_clibs_linux.sh
       - if: runner.os == 'macOS'
         name: prepare-macos
         run: |
-          brew install llvm@11
-          curl -L https://github.com/odin-lang/Odin/releases/download/dev-2023-07/odin-macos-amd64-dev-2023-07.zip --output odin.zip
+          brew install llvm@14
+          curl -L https://github.com/odin-lang/Odin/releases/download/dev-2023-08/odin-macos-amd64-dev-2023-08.zip --output odin.zip
           unzip odin.zip
           chmod a+x ./odin
           ./build_clibs_macos.sh
@@ -182,7 +184,7 @@ jobs:
         name: prepare-windows
         shell: cmd
         run: |
-          curl -L https://github.com/odin-lang/Odin/releases/download/dev-2023-07/odin-windows-amd64-dev-2023-07.zip --output odin.zip
+          curl -L https://github.com/odin-lang/Odin/releases/download/dev-2023-08/odin-windows-amd64-dev-2023-08.zip --output odin.zip
           unzip odin.zip
           build_clibs_windows.cmd
       - name: build

+ 6 - 0
CHANGELOG.md

@@ -1,5 +1,11 @@
 ## Updates
 
+#### 28-Aug-2023
+
+**sokol_gfx.h metal**: A new attempt at fixing a rare Metal validation layer
+error for MTKView swapchain resources. See ticket PR https://github.com/floooh/sokol/pull/873
+for details.
+
 #### 26-Jul-2023
 
 **sokol_nuklear.h**: The same image+sampler support has been added as in sokol_imgui.h

+ 8 - 11
sokol_gfx.h

@@ -4787,7 +4787,6 @@ typedef struct {
     id<MTLDevice> device;
     id<MTLCommandQueue> cmd_queue;
     id<MTLCommandBuffer> cmd_buffer;
-    id<MTLCommandBuffer> present_cmd_buffer;
     id<MTLRenderCommandEncoder> cmd_encoder;
     id<MTLBuffer> uniform_buffers[SG_NUM_INFLIGHT_FRAMES];
 } _sg_mtl_backend_t;
@@ -10599,7 +10598,8 @@ _SOKOL_PRIVATE void _sg_mtl_init_pool(const sg_desc* desc) {
             1 * desc->sampler_pool_size +
             4 * desc->shader_pool_size +
             2 * desc->pipeline_pool_size +
-            desc->pass_pool_size
+            desc->pass_pool_size +
+            128
         );
     _sg.mtl.idpool.pool = [NSMutableArray arrayWithCapacity:(NSUInteger)_sg.mtl.idpool.num_slots];
     _SG_OBJC_RETAIN(_sg.mtl.idpool.pool);
@@ -10924,7 +10924,6 @@ _SOKOL_PRIVATE void _sg_mtl_discard_backend(void) {
     }
     // NOTE: MTLCommandBuffer and MTLRenderCommandEncoder are auto-released
     _sg.mtl.cmd_buffer = nil;
-    _sg.mtl.present_cmd_buffer = nil;
     _sg.mtl.cmd_encoder = nil;
 }
 
@@ -11489,14 +11488,11 @@ _SOKOL_PRIVATE void _sg_mtl_begin_pass(_sg_pass_t* pass, const sg_pass_action* a
         Also see: https://github.com/floooh/sokol/issues/762
     */
     if (nil == _sg.mtl.cmd_buffer) {
-        SOKOL_ASSERT(nil == _sg.mtl.present_cmd_buffer);
         // block until the oldest frame in flight has finished
         dispatch_semaphore_wait(_sg.mtl.sem, DISPATCH_TIME_FOREVER);
         _sg.mtl.cmd_buffer = [_sg.mtl.cmd_queue commandBufferWithUnretainedReferences];
-        _sg.mtl.present_cmd_buffer =  [_sg.mtl.cmd_queue commandBuffer];
         [_sg.mtl.cmd_buffer enqueue];
-        [_sg.mtl.present_cmd_buffer enqueue];
-        [_sg.mtl.present_cmd_buffer addCompletedHandler:^(id<MTLCommandBuffer> cmd_buf) {
+        [_sg.mtl.cmd_buffer addCompletedHandler:^(id<MTLCommandBuffer> cmd_buf) {
             // NOTE: this code is called on a different thread!
             _SOKOL_UNUSED(cmd_buf);
             dispatch_semaphore_signal(_sg.mtl.sem);
@@ -11520,6 +11516,10 @@ _SOKOL_PRIVATE void _sg_mtl_begin_pass(_sg_pass_t* pass, const sg_pass_action* a
         } else {
             pass_desc = (__bridge MTLRenderPassDescriptor*) _sg.mtl.renderpass_descriptor_userdata_cb(_sg.mtl.user_data);
         }
+        // pin the swapchain resources into memory so that they outlive their command buffer
+        // (this is necessary because the command buffer doesn't retain references)
+        int default_pass_desc_ref = _sg_mtl_add_resource(pass_desc);
+        _sg_mtl_release_resource(_sg.mtl.frame_index, default_pass_desc_ref);
     }
     if (pass_desc) {
         _sg.mtl.pass_valid = true;
@@ -11651,7 +11651,6 @@ _SOKOL_PRIVATE void _sg_mtl_commit(void) {
     SOKOL_ASSERT(_sg.mtl.drawable_cb || _sg.mtl.drawable_userdata_cb);
     SOKOL_ASSERT(nil == _sg.mtl.cmd_encoder);
     SOKOL_ASSERT(nil != _sg.mtl.cmd_buffer);
-    SOKOL_ASSERT(nil != _sg.mtl.present_cmd_buffer);
 
     // present, commit and signal semaphore when done
     id<MTLDrawable> cur_drawable = nil;
@@ -11661,10 +11660,9 @@ _SOKOL_PRIVATE void _sg_mtl_commit(void) {
         cur_drawable = (__bridge id<MTLDrawable>) _sg.mtl.drawable_userdata_cb(_sg.mtl.user_data);
     }
     if (nil != cur_drawable) {
-        [_sg.mtl.present_cmd_buffer presentDrawable:cur_drawable];
+        [_sg.mtl.cmd_buffer presentDrawable:cur_drawable];
     }
     [_sg.mtl.cmd_buffer commit];
-    [_sg.mtl.present_cmd_buffer commit];
 
     // garbage-collect resources pending for release
     _sg_mtl_garbage_collect(_sg.mtl.frame_index);
@@ -11678,7 +11676,6 @@ _SOKOL_PRIVATE void _sg_mtl_commit(void) {
     _sg.mtl.cur_ub_base_ptr = 0;
     // NOTE: MTLCommandBuffer is autoreleased
     _sg.mtl.cmd_buffer = nil;
-    _sg.mtl.present_cmd_buffer = nil;
 }
 
 _SOKOL_PRIVATE void _sg_mtl_apply_viewport(int x, int y, int w, int h, bool origin_top_left) {