浏览代码

sokol_gfx.h: remove sg_begin_default_pass and fix metal backend for those changes

Andre Weissflog 1 年之前
父节点
当前提交
0fae329ae9
共有 1 个文件被更改,包括 101 次插入117 次删除
  1. 101 117
      sokol_gfx.h

+ 101 - 117
sokol_gfx.h

@@ -2351,13 +2351,37 @@ typedef struct sg_pass_action {
 
     FIXME
 */
+typedef struct sg_metal_swapchain {
+    // FIXME: replace with textures and setup RenderPassDescriptor in begin-pass?
+    const void* render_pass_descriptor; // MTLRenderPassDescriptor
+    const void* drawable;               // MTLDrawable
+} sg_metal_swapchain;
+
+typedef struct sg_d3d11_swapchain {
+    const void* render_target_view;     // ID3D11RenderTargetView
+    const void* depth_stencil_view;     // ID3D11DepthStencilView
+} sg_d3d11_swapchain;
+
+typedef struct sg_wgpu_swapchain {
+    const void* render_view;            // WGPUTextureView
+    const void* resolve_view;           // WGPUTextureView
+    const void* depth_stencil_view;     // WGPUTextureView
+} sg_wgpu_swapchain;
+
+typedef struct sg_gl_swapchain {
+    uint32_t framebuffer;               // GL framebuffer object
+} sg_gl_swapchain;
+
 typedef struct sg_swapchain {
     int width;
     int height;
     int sample_count;
     sg_pixel_format color_format;
     sg_pixel_format depth_format;
-    // FIXME: platform-specific swapchain surfaces
+    sg_metal_swapchain metal;
+    sg_d3d11_swapchain d3d11;
+    sg_wgpu_swapchain wgpu;
+    sg_gl_swapchain gl;
 } sg_swapchain;
 
 /*
@@ -3393,7 +3417,8 @@ typedef struct sg_frame_stats {
     _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE_NO_RT, "pass depth attachment image must be have render_target=true") \
     _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE_SIZES, "pass depth attachment image size must match color attachment image size") \
     _SG_LOGITEM_XMACRO(VALIDATE_ATTACHMENTSDESC_DEPTH_IMAGE_SAMPLE_COUNT, "pass depth attachment sample count must match color attachment sample count") \
-    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_PASS, "sg_begin_pass: pass must be valid") \
+    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_ATTACHMENTS_EXISTS, "sg_begin_pass: attachments object no longer alive") \
+    _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_ATTACHMENTS_VALID, "sg_begin_pass: attachemnts object not in resource state VALID") \
     _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_COLOR_ATTACHMENT_IMAGE, "sg_begin_pass: one or more color attachment images are not valid") \
     _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_RESOLVE_ATTACHMENT_IMAGE, "sg_begin_pass: one or more resolve attachment images are not valid") \
     _SG_LOGITEM_XMACRO(VALIDATE_BEGINPASS_DEPTHSTENCIL_ATTACHMENT_IMAGE, "sg_begin_pass: one or more depth-stencil attachment images are not valid") \
@@ -3595,40 +3620,17 @@ typedef enum sg_log_item {
 */
 typedef struct sg_metal_context_desc {
     const void* device;
-    const void* (*renderpass_descriptor_cb)(void);
-    const void* (*renderpass_descriptor_userdata_cb)(void*);
-    const void* (*drawable_cb)(void);
-    const void* (*drawable_userdata_cb)(void*);
-    void* user_data;
 } sg_metal_context_desc;
 
 typedef struct sg_d3d11_context_desc {
     const void* device;
     const void* device_context;
-    const void* (*render_target_view_cb)(void);
-    const void* (*render_target_view_userdata_cb)(void*);
-    const void* (*depth_stencil_view_cb)(void);
-    const void* (*depth_stencil_view_userdata_cb)(void*);
-    void* user_data;
 } sg_d3d11_context_desc;
 
 typedef struct sg_wgpu_context_desc {
     const void* device;                    // WGPUDevice
-    const void* (*render_view_cb)(void);   // returns WGPUTextureView
-    const void* (*render_view_userdata_cb)(void*);
-    const void* (*resolve_view_cb)(void);  // returns WGPUTextureView
-    const void* (*resolve_view_userdata_cb)(void*);
-    const void* (*depth_stencil_view_cb)(void);    // returns WGPUTextureView
-    const void* (*depth_stencil_view_userdata_cb)(void*);
-    void* user_data;
 } sg_wgpu_context_desc;
 
-typedef struct sg_gl_context_desc {
-    uint32_t (*default_framebuffer_cb)(void);
-    uint32_t (*default_framebuffer_userdata_cb)(void*);
-    void* user_data;
-} sg_gl_context_desc;
-
 typedef struct sg_context_desc {
     sg_pixel_format color_format;
     sg_pixel_format depth_format;
@@ -3636,7 +3638,6 @@ typedef struct sg_context_desc {
     sg_metal_context_desc metal;
     sg_d3d11_context_desc d3d11;
     sg_wgpu_context_desc wgpu;
-    sg_gl_context_desc gl;
 } sg_context_desc;
 
 /*
@@ -3740,8 +3741,6 @@ SOKOL_GFX_API_DECL bool sg_query_buffer_overflow(sg_buffer buf);
 SOKOL_GFX_API_DECL bool sg_query_buffer_will_overflow(sg_buffer buf, size_t size);
 
 // rendering functions
-SOKOL_GFX_API_DECL void sg_begin_default_pass(const sg_pass_action* pass_action, int width, int height);
-SOKOL_GFX_API_DECL void sg_begin_default_passf(const sg_pass_action* pass_action, float width, float height);
 SOKOL_GFX_API_DECL void sg_begin_pass(const sg_pass* pass);
 SOKOL_GFX_API_DECL void sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left);
 SOKOL_GFX_API_DECL void sg_apply_viewportf(float x, float y, float width, float height, bool origin_top_left);
@@ -4028,8 +4027,6 @@ inline sg_pipeline sg_make_pipeline(const sg_pipeline_desc& desc) { return sg_ma
 inline sg_pass sg_make_attchments(const sg_attachments_desc& desc) { return sg_make_attachments(&desc); }
 inline void sg_update_image(sg_image img, const sg_image_data& data) { return sg_update_image(img, &data); }
 
-inline void sg_begin_default_pass(const sg_pass_action& pass_action, int width, int height) { return sg_begin_default_pass(&pass_action, width, height); }
-inline void sg_begin_default_passf(const sg_pass_action& pass_action, float width, float height) { return sg_begin_default_passf(&pass_action, width, height); }
 inline void sg_begin_pass(const sg_pass& pass) { return sg_begin_pass(&pass); }
 inline void sg_apply_bindings(const sg_bindings& bindings) { return sg_apply_bindings(&bindings); }
 inline void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const sg_range& data) { return sg_apply_uniforms(stage, ub_index, &data); }
@@ -5337,11 +5334,6 @@ typedef struct {
 typedef struct {
     bool valid;
     bool use_shared_storage_mode;
-    const void*(*renderpass_descriptor_cb)(void);
-    const void*(*renderpass_descriptor_userdata_cb)(void*);
-    const void*(*drawable_cb)(void);
-    const void*(*drawable_userdata_cb)(void*);
-    void* user_data;
     uint32_t cur_frame_rotate_index;
     int ub_size;
     int cur_ub_offset;
@@ -5357,6 +5349,7 @@ typedef struct {
     id<MTLCommandQueue> cmd_queue;
     id<MTLCommandBuffer> cmd_buffer;
     id<MTLRenderCommandEncoder> cmd_encoder;
+    id<MTLDrawable> cur_drawable;
     id<MTLBuffer> uniform_buffers[SG_NUM_INFLIGHT_FRAMES];
 } _sg_mtl_backend_t;
 
@@ -11627,17 +11620,10 @@ _SOKOL_PRIVATE void _sg_mtl_setup_backend(const sg_desc* desc) {
     // assume already zero-initialized
     SOKOL_ASSERT(desc);
     SOKOL_ASSERT(desc->context.metal.device);
-    SOKOL_ASSERT(desc->context.metal.renderpass_descriptor_cb || desc->context.metal.renderpass_descriptor_userdata_cb);
-    SOKOL_ASSERT(desc->context.metal.drawable_cb || desc->context.metal.drawable_userdata_cb);
     SOKOL_ASSERT(desc->uniform_buffer_size > 0);
     _sg_mtl_init_pool(desc);
     _sg_mtl_clear_state_cache();
     _sg.mtl.valid = true;
-    _sg.mtl.renderpass_descriptor_cb = desc->context.metal.renderpass_descriptor_cb;
-    _sg.mtl.renderpass_descriptor_userdata_cb = desc->context.metal.renderpass_descriptor_userdata_cb;
-    _sg.mtl.drawable_cb = desc->context.metal.drawable_cb;
-    _sg.mtl.drawable_userdata_cb = desc->context.metal.drawable_userdata_cb;
-    _sg.mtl.user_data = desc->context.metal.user_data;
     _sg.mtl.ub_size = desc->uniform_buffer_size;
     _sg.mtl.sem = dispatch_semaphore_create(SG_NUM_INFLIGHT_FRAMES);
     _sg.mtl.device = (__bridge id<MTLDevice>) desc->context.metal.device;
@@ -12267,15 +12253,23 @@ _SOKOL_PRIVATE _sg_image_t* _sg_mtl_attachments_ds_image(const _sg_attachments_t
     return atts->mtl.depth_stencil.image;
 }
 
-_SOKOL_PRIVATE void _sg_mtl_begin_pass(_sg_attachments_t* atts, const sg_pass_action* action, int w, int h) {
+_SOKOL_PRIVATE void _sg_mtl_begin_pass(const sg_pass_action* action, _sg_attachments_t* atts, const sg_swapchain* swapchain) {
     SOKOL_ASSERT(action);
+    SOKOL_ASSERT(swapchain);
     SOKOL_ASSERT(!_sg.mtl.in_pass);
     SOKOL_ASSERT(_sg.mtl.cmd_queue);
     SOKOL_ASSERT(nil == _sg.mtl.cmd_encoder);
-    SOKOL_ASSERT(_sg.mtl.renderpass_descriptor_cb || _sg.mtl.renderpass_descriptor_userdata_cb);
+    SOKOL_ASSERT(nil == _sg.mtl.cur_drawable);
     _sg.mtl.in_pass = true;
-    _sg.mtl.cur_width = w;
-    _sg.mtl.cur_height = h;
+    if (atts) {
+        _sg.mtl.cur_width = atts->cmn.width;
+        _sg.mtl.cur_height = atts->cmn.height;
+    } else {
+        SOKOL_ASSERT(swapchain->width > 0);
+        SOKOL_ASSERT(swapchain->height > 0);
+        _sg.mtl.cur_width = swapchain->width;
+        _sg.mtl.cur_height = swapchain->height;
+    }
     _sg_mtl_clear_state_cache();
 
     /*
@@ -12312,24 +12306,21 @@ _SOKOL_PRIVATE void _sg_mtl_begin_pass(_sg_attachments_t* atts, const sg_pass_ac
         // offscreen render pass
         pass_desc = [MTLRenderPassDescriptor renderPassDescriptor];
     } else {
-        // default render pass, call user-provided callback to provide render pass descriptor
-        if (_sg.mtl.renderpass_descriptor_cb) {
-            pass_desc = (__bridge MTLRenderPassDescriptor*) _sg.mtl.renderpass_descriptor_cb();
-        } else {
-            pass_desc = (__bridge MTLRenderPassDescriptor*) _sg.mtl.renderpass_descriptor_userdata_cb(_sg.mtl.user_data);
+        // a swapchain pass descriptor will not be valid if window is minimized, don't do any rendering in this case
+        if (0 == swapchain->metal.render_pass_descriptor) {
+            _sg.mtl.pass_valid = false;
+            return;
         }
+        pass_desc = (__bridge MTLRenderPassDescriptor*) swapchain->metal.render_pass_descriptor;
         // 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.frame_index, default_pass_desc_ref);
+        SOKOL_ASSERT(swapchain->metal.drawable);
+        _sg.mtl.cur_drawable = (__bridge id<MTLDrawable>) swapchain->metal.drawable;
     }
-    if (pass_desc) {
-        _sg.mtl.pass_valid = true;
-    } else {
-        // default pass descriptor will not be valid if window is minimized, don't do any rendering in this case
-        _sg.mtl.pass_valid = false;
-        return;
-    }
+    SOKOL_ASSERT(pass_desc);
+    _sg.mtl.pass_valid = true;
     if (atts) {
         // setup pass descriptor for offscreen rendering
         SOKOL_ASSERT(atts->slot.state == SG_RESOURCESTATE_VALID);
@@ -12445,25 +12436,20 @@ _SOKOL_PRIVATE void _sg_mtl_end_pass(void) {
         // NOTE: MTLRenderCommandEncoder is autoreleased
         _sg.mtl.cmd_encoder = nil;
     }
+    // if this is a swapchain pass, present the drawable
+    if (nil != _sg.mtl.cur_drawable) {
+        [_sg.mtl.cmd_buffer presentDrawable:_sg.mtl.cur_drawable];
+        _sg.mtl.cur_drawable = nil;
+    }
 }
 
 _SOKOL_PRIVATE void _sg_mtl_commit(void) {
     SOKOL_ASSERT(!_sg.mtl.in_pass);
     SOKOL_ASSERT(!_sg.mtl.pass_valid);
-    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);
 
-    // present, commit and signal semaphore when done
-    id<MTLDrawable> cur_drawable = nil;
-    if (_sg.mtl.drawable_cb) {
-        cur_drawable = (__bridge id<MTLDrawable>) _sg.mtl.drawable_cb();
-    } else {
-        cur_drawable = (__bridge id<MTLDrawable>) _sg.mtl.drawable_userdata_cb(_sg.mtl.user_data);
-    }
-    if (nil != cur_drawable) {
-        [_sg.mtl.cmd_buffer presentDrawable:cur_drawable];
-    }
+    // commit the frame's command buffer
     [_sg.mtl.cmd_buffer commit];
 
     // garbage-collect resources pending for release
@@ -14910,17 +14896,17 @@ static inline _sg_image_t* _sg_attachments_ds_image(const _sg_attachments_t* att
     #endif
 }
 
-static inline void _sg_begin_pass(_sg_attachments_t* atts, const sg_pass_action* action, int w, int h) {
+static inline void _sg_begin_pass(const sg_pass_action* action, _sg_attachments_t* atts, const sg_swapchain* swapchain) {
     #if defined(_SOKOL_ANY_GL)
-    _sg_gl_begin_pass(atts, action, w, h);
+    _sg_gl_begin_pass(action, atts, swapchain);
     #elif defined(SOKOL_METAL)
-    _sg_mtl_begin_pass(atts, action, w, h);
+    _sg_mtl_begin_pass(action, atts, swapchain);
     #elif defined(SOKOL_D3D11)
-    _sg_d3d11_begin_pass(atts, action, w, h);
+    _sg_d3d11_begin_pass(action, atts, swapchain);
     #elif defined(SOKOL_WGPU)
-    _sg_wgpu_begin_pass(atts, action, w, h);
+    _sg_wgpu_begin_pass(action, atts, swapchain);
     #elif defined(SOKOL_DUMMY_BACKEND)
-    _sg_dummy_begin_pass(atts, action, w, h);
+    _sg_dummy_begin_pass(action, atts, swapchain);
     #else
     #error("INVALID BACKEND");
     #endif
@@ -15945,7 +15931,7 @@ _SOKOL_PRIVATE bool _sg_validate_attachments_desc(const sg_attachments_desc* des
     #endif
 }
 
-_SOKOL_PRIVATE bool _sg_validate_begin_pass(_sg_attachments_t* atts) {
+_SOKOL_PRIVATE bool _sg_validate_begin_pass(const sg_pass* pass) {
     #if !defined(SOKOL_DEBUG)
         _SOKOL_UNUSED(pass);
         return true;
@@ -15954,26 +15940,35 @@ _SOKOL_PRIVATE bool _sg_validate_begin_pass(_sg_attachments_t* atts) {
             return true;
         }
         _sg_validate_begin();
-        _SG_VALIDATE(atts->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_PASS);
-        for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
-            const _sg_attachment_common_t* color_att = &atts->cmn.colors[i];
-            const _sg_image_t* color_img = _sg_attachments_color_image(atts, i);
-            if (color_img) {
-                _SG_VALIDATE(color_img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_COLOR_ATTACHMENT_IMAGE);
-                _SG_VALIDATE(color_img->slot.id == color_att->image_id.id, VALIDATE_BEGINPASS_COLOR_ATTACHMENT_IMAGE);
+        if (pass->attachments.id == SG_INVALID_ID) {
+            // this is a swapchain pass
+            // FIXME: validate swapchain params!
+        } else {
+            // this is an 'offscreen pass'
+            const _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, pass->attachments.id);
+            _SG_VALIDATE(atts != 0, VALIDATE_BEGINPASS_ATTACHMENTS_EXISTS);
+            _SG_VALIDATE(atts->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_ATTACHMENTS_VALID);
+            for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) {
+                const _sg_attachment_common_t* color_att = &atts->cmn.colors[i];
+                const _sg_image_t* color_img = _sg_attachments_color_image(atts, i);
+                if (color_img) {
+                    _SG_VALIDATE(color_img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_COLOR_ATTACHMENT_IMAGE);
+                    _SG_VALIDATE(color_img->slot.id == color_att->image_id.id, VALIDATE_BEGINPASS_COLOR_ATTACHMENT_IMAGE);
+                }
+                const _sg_attachment_common_t* resolve_att = &atts->cmn.resolves[i];
+                const _sg_image_t* resolve_img = _sg_attachments_resolve_image(atts, i);
+                if (resolve_img) {
+                    _SG_VALIDATE(resolve_img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_RESOLVE_ATTACHMENT_IMAGE);
+                    _SG_VALIDATE(resolve_img->slot.id == resolve_att->image_id.id, VALIDATE_BEGINPASS_RESOLVE_ATTACHMENT_IMAGE);
+                }
             }
-            const _sg_attachment_common_t* resolve_att = &atts->cmn.resolves[i];
-            const _sg_image_t* resolve_img = _sg_attachments_resolve_image(atts, i);
-            if (resolve_img) {
-                _SG_VALIDATE(resolve_img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_RESOLVE_ATTACHMENT_IMAGE);
-                _SG_VALIDATE(resolve_img->slot.id == resolve_att->image_id.id, VALIDATE_BEGINPASS_RESOLVE_ATTACHMENT_IMAGE);
+            const _sg_image_t* ds_img = _sg_attachments_ds_image(atts);
+            if (ds_img) {
+                const _sg_attachment_common_t* att = &atts->cmn.depth_stencil;
+                _SG_VALIDATE(ds_img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_DEPTHSTENCIL_ATTACHMENT_IMAGE);
+                _SG_VALIDATE(ds_img->slot.id == att->image_id.id, VALIDATE_BEGINPASS_DEPTHSTENCIL_ATTACHMENT_IMAGE);
             }
-        }
-        const _sg_image_t* ds_img = _sg_attachments_ds_image(atts);
-        if (ds_img) {
-            const _sg_attachment_common_t* att = &atts->cmn.depth_stencil;
-            _SG_VALIDATE(ds_img->slot.state == SG_RESOURCESTATE_VALID, VALIDATE_BEGINPASS_DEPTHSTENCIL_ATTACHMENT_IMAGE);
-            _SG_VALIDATE(ds_img->slot.id == att->image_id.id, VALIDATE_BEGINPASS_DEPTHSTENCIL_ATTACHMENT_IMAGE);
+            // FIXME: swapchain params must be all zero!
         }
         return _sg_validate_end();
     #endif
@@ -16018,6 +16013,7 @@ _SOKOL_PRIVATE bool _sg_validate_apply_pipeline(sg_pipeline pip_id) {
             }
         } else {
             // default pass
+            // FIXME: match against swapchain attributes
             _SG_VALIDATE(pip->cmn.color_count == 1, VALIDATE_APIP_ATT_COUNT);
             _SG_VALIDATE(pip->cmn.colors[0].pixel_format == _sg.desc.context.color_format, VALIDATE_APIP_COLOR_FORMAT);
             _SG_VALIDATE(pip->cmn.depth.pixel_format == _sg.desc.context.depth_format, VALIDATE_APIP_DEPTH_FORMAT);
@@ -17547,40 +17543,28 @@ SOKOL_API_IMPL void sg_destroy_attachments(sg_attachments atts_id) {
     }
 }
 
-SOKOL_API_IMPL void sg_begin_default_pass(const sg_pass_action* pass_action, int width, int height) {
-    SOKOL_ASSERT(_sg.valid);
-    SOKOL_ASSERT(pass_action);
-    sg_pass_action pa;
-    _sg_resolve_pass_action(pass_action, &pa);
-    _sg.cur_atts.id = SG_INVALID_ID;
-    _sg.pass_valid = true;
-    _sg_begin_pass(0, &pa, width, height);
-    _SG_TRACE_ARGS(begin_default_pass, &pa, width, height);
-}
-
-SOKOL_API_IMPL void sg_begin_default_passf(const sg_pass_action* pass_action, float width, float height) {
-    sg_begin_default_pass(pass_action, (int)width, (int)height);
-}
-
 SOKOL_API_IMPL void sg_begin_pass(const sg_pass* pass) {
     SOKOL_ASSERT(_sg.valid);
     SOKOL_ASSERT(pass);
     SOKOL_ASSERT((pass->_start_canary == 0) && (pass->_end_canary == 0));
     _sg.pass_valid = false;
     _sg.cur_atts.id = SG_INVALID_ID;
-    _sg_attachments_t* atts = _sg_lookup_attachments(&_sg.pools, pass->attachments.id);
-    if (0 == atts) {
-        _SG_ERROR(BEGINPASS_ATTACHMENT_INVALID);
+    if (!_sg_validate_begin_pass(pass)) {
         return;
     }
-    if (!_sg_validate_begin_pass(atts)) {
-        return;
+    _sg_attachments_t* atts = 0;
+    if (pass->attachments.id != SG_INVALID_ID) {
+        atts = _sg_lookup_attachments(&_sg.pools, pass->attachments.id);
+        if (0 == atts) {
+            _SG_ERROR(BEGINPASS_ATTACHMENT_INVALID);
+            return;
+        }
+        _sg.cur_atts = pass->attachments;
     }
-    _sg.pass_valid = true;
-    _sg.cur_atts = pass->attachments;
     sg_pass_action pa;
     _sg_resolve_pass_action(&pass->action, &pa);
-    _sg_begin_pass(atts, &pa, atts->cmn.width, atts->cmn.height);
+    _sg.pass_valid = true;
+    _sg_begin_pass(&pa, atts, &pass->swapchain);
     _SG_TRACE_ARGS(begin_pass, pass);
 }