From 500f916540c9754733fee128ed286ed391ddb60b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Fri, 2 Oct 2026 16:00:20 -0700 Subject: [PATCH] Relaxed view maximum, made view storage grow with use, up-to 4096 view ids. (#4014) --- bindings/bf/bgfx.bf | 15 +- bindings/c3/bgfx.c3 | 29 +- bindings/cs/bgfx.cs | 15 +- bindings/d/package.d | 34 ++- bindings/py/bgfx.py | 1 + bindings/py/bgfx.pyi | 29 +- bindings/zig/bgfx.zig | 15 +- docs/internals.rst | 10 +- examples/09-hdr/hdr.cpp | 4 +- examples/common/imgui/imgui.cpp | 2 +- examples/common/imgui/imgui.h | 2 +- include/bgfx/bgfx.h | 28 +- include/bgfx/c99/bgfx.h | 32 ++- include/bgfx/defines.h | 2 +- scripts/bgfx.idl | 30 +- src/bgfx.cpp | 116 ++++++-- src/bgfx_p.h | 466 +++++++++++++++++++++++++++++--- src/config.h | 58 +++- src/renderer.h | 129 ++++++--- src/renderer_d3d11.cpp | 52 ++-- src/renderer_d3d11.h | 18 +- src/renderer_d3d12.cpp | 57 ++-- src/renderer_d3d12.h | 10 +- src/renderer_gl.cpp | 38 +-- src/renderer_gl.h | 16 +- src/renderer_mtl.cpp | 55 ++-- src/renderer_mtl.h | 8 +- src/renderer_vk.cpp | 54 ++-- src/renderer_vk.h | 10 +- src/renderer_webgpu.cpp | 94 +++++-- src/renderer_webgpu.h | 26 +- 31 files changed, 1064 insertions(+), 391 deletions(-) diff --git a/bindings/bf/bgfx.bf b/bindings/bf/bgfx.bf index e8eb860c2..4b6ce0b42 100644 --- a/bindings/bf/bgfx.bf +++ b/bindings/bf/bgfx.bf @@ -2701,6 +2701,7 @@ public static class bgfx public uint16 maxEncoders; public uint32 numDrawCalls; public uint32 numDrawCallPeakFrames; + public uint32 minViews; public uint32 minResourceCbSize; public uint32 maxTransientVbSize; public uint32 maxTransientIbSize; @@ -4328,10 +4329,10 @@ public static class bgfx /// /// In graphics debugger view name will appear as: /// - /// "nnnc " - /// ^ ^ ^ - /// | +--- compute (C) - /// +------ view id + /// "nnnnc " + /// ^ ^ ^ + /// | +--- compute (C) + /// +------- view id /// /// /// @@ -4484,7 +4485,9 @@ public static class bgfx public static extern void set_view_transform(ViewId _id, void* _view, void* _proj); /// - /// Post submit view reordering. + /// Post submit view reordering. A view in `_order` that currently renders + /// outside the remapped range swaps places with the view it displaces, so the + /// order stays a permutation of all view ids. /// /// /// First view id. @@ -4508,7 +4511,7 @@ public static class bgfx public static extern void set_view_shading_rate(ViewId _id, ShadingRate _shadingRate); /// - /// Reset all view settings to default. + /// Reset all view settings to default, including the view name. /// /// /// _id View id. diff --git a/bindings/c3/bgfx.c3 b/bindings/c3/bgfx.c3 index f1ce29729..a8e590277 100644 --- a/bindings/c3/bgfx.c3 +++ b/bindings/c3/bgfx.c3 @@ -1853,13 +1853,22 @@ struct InitLimits // `Stats::numDrawCallsPeak` to size it. uint numDrawCalls; // Number of frames the draw-call peak (high-water mark) is observed - // before unused storage is released. Also used for resource command - // buffers and uniform buffers. Set to 0 to keep whatever has been - // allocated for the lifetime of the context. With + // before unused storage is released. Also used for view storage, + // resource command buffers and uniform buffers. Set to 0 to keep + // whatever has been allocated for the lifetime of the context. With // `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled draw/blit/rect storage // is not resized; unused uniform and resource command buffer space // is still released. uint numDrawCallPeakFrames; + // Minimum number of views to keep state for. Rounded up to a + // multiple of 64. This is a reservation, not a limit: a view past it + // gets storage when it is first set, up to + // `Caps::Limits::maxViews`, and that storage is released again once + // the views sharing it are all reset. Per-frame view data is sized + // by the views used in a frame, see `numDrawCallPeakFrames`. With + // `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled storage for all views + // is allocated up front. + uint minViews; // Minimum resource command buffer size. uint minResourceCbSize; // Maximum transient vertex buffer size. @@ -3170,10 +3179,10 @@ extern fn void set_palette_color_rgba8(char _index, uint _rgba) @cname("bgfx_set // // In graphics debugger view name will appear as: // -// "nnnc " -// ^ ^ ^ -// | +--- compute (C) -// +------ view id +// "nnnnc " +// ^ ^ ^ +// | +--- compute (C) +// +------- view id // // _id : `View id.` // _name : `View name.` @@ -3271,7 +3280,9 @@ extern fn void set_view_frame_buffer(ushort _id, FrameBufferHandle _handle) @cna // _proj : `Projection matrix.` extern fn void set_view_transform(ushort _id, void* _view, void* _proj) @cname("bgfx_set_view_transform"); -// Post submit view reordering. +// Post submit view reordering. A view in `_order` that currently renders +// outside the remapped range swaps places with the view it displaces, so the +// order stays a permutation of all view ids. // _id : `First view id.` // _num : `Number of views to remap.` // _order : `View remap id table. Passing `NULL` will reset view ids to default state.` @@ -3285,7 +3296,7 @@ extern fn void set_view_order(ushort _id, ushort _num, ushort* _order) @cname("b // _shadingRate : `Shading rate.` extern fn void set_view_shading_rate(ushort _id, ShadingRate _shadingRate) @cname("bgfx_set_view_shading_rate"); -// Reset all view settings to default. +// Reset all view settings to default, including the view name. // _id : `_id View id.` extern fn void reset_view(ushort _id) @cname("bgfx_reset_view"); diff --git a/bindings/cs/bgfx.cs b/bindings/cs/bgfx.cs index d0e3b751d..3725c65f4 100644 --- a/bindings/cs/bgfx.cs +++ b/bindings/cs/bgfx.cs @@ -2674,6 +2674,7 @@ public static partial class bgfx public ushort maxEncoders; public uint numDrawCalls; public uint numDrawCallPeakFrames; + public uint minViews; public uint minResourceCbSize; public uint maxTransientVbSize; public uint maxTransientIbSize; @@ -4275,10 +4276,10 @@ public static partial class bgfx /// /// In graphics debugger view name will appear as: /// - /// "nnnc " - /// ^ ^ ^ - /// | +--- compute (C) - /// +------ view id + /// "nnnnc " + /// ^ ^ ^ + /// | +--- compute (C) + /// +------- view id /// /// /// @@ -4431,7 +4432,9 @@ public static partial class bgfx public static extern unsafe void set_view_transform(ushort _id, void* _view, void* _proj); /// - /// Post submit view reordering. + /// Post submit view reordering. A view in `_order` that currently renders + /// outside the remapped range swaps places with the view it displaces, so the + /// order stays a permutation of all view ids. /// /// /// First view id. @@ -4455,7 +4458,7 @@ public static partial class bgfx public static extern unsafe void set_view_shading_rate(ushort _id, ShadingRate _shadingRate); /// - /// Reset all view settings to default. + /// Reset all view settings to default, including the view name. /// /// /// _id View id. diff --git a/bindings/d/package.d b/bindings/d/package.d index 328493016..935b9cf96 100644 --- a/bindings/d/package.d +++ b/bindings/d/package.d @@ -9,7 +9,7 @@ import bindbc.common.types: c_int64, c_uint64, va_list; import bindbc.bgfx.config; static import bgfx.impl; -enum uint apiVersion = 162; +enum uint apiVersion = 163; alias ViewID = ushort; @@ -1360,14 +1360,26 @@ extern(C++, "bgfx") struct Init{ /** Number of frames the draw-call peak (high-water mark) is observed - before unused storage is released. Also used for resource command - buffers and uniform buffers. Set to 0 to keep whatever has been - allocated for the lifetime of the context. With + before unused storage is released. Also used for view storage, + resource command buffers and uniform buffers. Set to 0 to keep + whatever has been allocated for the lifetime of the context. With `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled draw/blit/rect storage is not resized; unused uniform and resource command buffer space is still released. */ uint numDrawCallPeakFrames; + + /** + Minimum number of views to keep state for. Rounded up to a + multiple of 64. This is a reservation, not a limit: a view past it + gets storage when it is first set, up to + `Caps::Limits::maxViews`, and that storage is released again once + the views sharing it are all reset. Per-frame view data is sized + by the views used in a frame, see `numDrawCallPeakFrames`. With + `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled storage for all views + is allocated up front. + */ + uint minViews; uint minResourceCBSize; ///Minimum resource command buffer size. uint maxTransientVBSize; ///Maximum transient vertex buffer size. uint maxTransientIBSize; ///Maximum transient index buffer size. @@ -3676,10 +3688,10 @@ mixin(joinFnBinds((){ * * In graphics debugger view name will appear as: * - * "nnnc " - * ^ ^ ^ - * | +--- compute (C) - * +------ view id + * "nnnnc " + * ^ ^ ^ + * | +--- compute (C) + * +------- view id * Params: id = View id. @@ -3820,7 +3832,9 @@ mixin(joinFnBinds((){ {q{void}, q{setViewTransform}, q{ViewID id, const(void)* view, const(void)* proj}, ext: `C++, "bgfx"`}, /** - * Post submit view reordering. + * Post submit view reordering. A view in `_order` that currently renders + * outside the remapped range swaps places with the view it displaces, so the + * order stays a permutation of all view ids. Params: id = First view id. num = Number of views to remap. @@ -3841,7 +3855,7 @@ mixin(joinFnBinds((){ {q{void}, q{setViewShadingRate}, q{ViewID id, bgfx.impl.ShadingRate.Enum shadingRate=ShadingRate.rate1x1}, ext: `C++, "bgfx"`}, /** - * Reset all view settings to default. + * Reset all view settings to default, including the view name. Params: id = _id View id. */ diff --git a/bindings/py/bgfx.py b/bindings/py/bgfx.py index 732768120..00039d4bf 100644 --- a/bindings/py/bgfx.py +++ b/bindings/py/bgfx.py @@ -905,6 +905,7 @@ InitLimits._fields_ = [ ("maxEncoders", ctypes.c_uint16), ("numDrawCalls", ctypes.c_uint32), ("numDrawCallPeakFrames", ctypes.c_uint32), + ("minViews", ctypes.c_uint32), ("minResourceCbSize", ctypes.c_uint32), ("maxTransientVbSize", ctypes.c_uint32), ("maxTransientIbSize", ctypes.c_uint32), diff --git a/bindings/py/bgfx.pyi b/bindings/py/bgfx.pyi index bcb7bbb60..1c1fa1dd2 100644 --- a/bindings/py/bgfx.pyi +++ b/bindings/py/bgfx.pyi @@ -1411,13 +1411,22 @@ class InitLimits(ctypes.Structure): # `Stats::numDrawCallsPeak` to size it. numDrawCalls: int # Number of frames the draw-call peak (high-water mark) is observed - # before unused storage is released. Also used for resource command - # buffers and uniform buffers. Set to 0 to keep whatever has been - # allocated for the lifetime of the context. With + # before unused storage is released. Also used for view storage, + # resource command buffers and uniform buffers. Set to 0 to keep + # whatever has been allocated for the lifetime of the context. With # `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled draw/blit/rect storage # is not resized; unused uniform and resource command buffer space # is still released. numDrawCallPeakFrames: int + # Minimum number of views to keep state for. Rounded up to a + # multiple of 64. This is a reservation, not a limit: a view past it + # gets storage when it is first set, up to + # `Caps::Limits::maxViews`, and that storage is released again once + # the views sharing it are all reset. Per-frame view data is sized + # by the views used in a frame, see `numDrawCallPeakFrames`. With + # `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled storage for all views + # is allocated up front. + minViews: int # Minimum resource command buffer size. minResourceCbSize: int # Maximum transient vertex buffer size. @@ -2574,10 +2583,10 @@ def bgfx_set_palette_color_rgba8(_index: int, _rgba: int, /) -> None: ... # # In graphics debugger view name will appear as: # -# "nnnc " -# ^ ^ ^ -# | +--- compute (C) -# +------ view id +# "nnnnc " +# ^ ^ ^ +# | +--- compute (C) +# +------- view id # def bgfx_set_view_name(_id: int, _name: Optional[bytes], _len: int, /) -> None: ... @@ -2649,7 +2658,9 @@ def bgfx_set_view_frame_buffer(_id: int, _handle: FrameBufferHandle, /) -> None: # all draw primitives in this view will use these two matrices. def bgfx_set_view_transform(_id: int, _view: Any, _proj: Any, /) -> None: ... -# Post submit view reordering. +# Post submit view reordering. A view in `_order` that currently renders +# outside the remapped range swaps places with the view it displaces, so the +# order stays a permutation of all view ids. def bgfx_set_view_order(_id: int, _num: int, _order: Any, /) -> None: ... # Set view shading rate. @@ -2658,7 +2669,7 @@ def bgfx_set_view_order(_id: int, _num: int, _order: Any, /) -> None: ... # def bgfx_set_view_shading_rate(_id: int, _shadingRate: Union[ShadingRate, int], /) -> None: ... -# Reset all view settings to default. +# Reset all view settings to default, including the view name. def bgfx_reset_view(_id: int, /) -> None: ... # Begin submitting draw calls from thread. Obtains an encoder that can be diff --git a/bindings/zig/bgfx.zig b/bindings/zig/bgfx.zig index 0f1df0bfd..6deca0946 100644 --- a/bindings/zig/bgfx.zig +++ b/bindings/zig/bgfx.zig @@ -1674,6 +1674,7 @@ pub const Init = extern struct { maxEncoders: u16, numDrawCalls: u32, numDrawCallPeakFrames: u32, + minViews: u32, minResourceCbSize: u32, maxTransientVbSize: u32, maxTransientIbSize: u32, @@ -3546,10 +3547,10 @@ extern fn bgfx_set_palette_color_rgba8(_index: u8, _rgba: u32) void; /// /// In graphics debugger view name will appear as: /// -/// "nnnc " -/// ^ ^ ^ -/// | +--- compute (C) -/// +------ view id +/// "nnnnc " +/// ^ ^ ^ +/// | +--- compute (C) +/// +------- view id /// /// View id. /// View name. @@ -3680,7 +3681,9 @@ pub inline fn setViewTransform(_id: ViewId, _view: ?*const anyopaque, _proj: ?*c } extern fn bgfx_set_view_transform(_id: ViewId, _view: ?*const anyopaque, _proj: ?*const anyopaque) void; -/// Post submit view reordering. +/// Post submit view reordering. A view in `_order` that currently renders +/// outside the remapped range swaps places with the view it displaces, so the +/// order stays a permutation of all view ids. /// First view id. /// Number of views to remap. /// View remap id table. Passing `NULL` will reset view ids to default state. @@ -3700,7 +3703,7 @@ pub inline fn setViewShadingRate(_id: ViewId, _shadingRate: ShadingRate) void { } extern fn bgfx_set_view_shading_rate(_id: ViewId, _shadingRate: ShadingRate) void; -/// Reset all view settings to default. +/// Reset all view settings to default, including the view name. /// _id View id. pub inline fn resetView(_id: ViewId) void { return bgfx_reset_view(_id); diff --git a/docs/internals.rst b/docs/internals.rst index 10b90c42d..4fd12c39a 100644 --- a/docs/internals.rst +++ b/docs/internals.rst @@ -90,7 +90,7 @@ Any API call starting with ``bgfx::setView*`` is considered part of the View API One important constraint: ``bgfx::setViewMode`` must be set **before** any draw calls are submitted to that view within a frame. The internal encoder reads the view mode at submit time to select the sort key encoding. Changing the view mode after draw calls have already been submitted to that view will cause incorrect sort behaviour. -The maximum number of views is configured by ``BGFX_CONFIG_MAX_VIEWS`` (default: 256, must be a power of 2). Views are referenced by ``ViewId`` (a 16-bit integer). +Views are referenced by ``ViewId`` (a 16-bit integer) in the range ``0`` to ``BGFX_CONFIG_MAX_VIEWS-1`` (4096 ids, fixed). View state is kept for ``Init::Limits::minViews`` views (``BGFX_CONFIG_MIN_VIEWS``, default 256) and allocated in blocks of 64 as views past that are set; a block whose views are all reset is released again once ``Init::Limits::numDrawCallPeakFrames`` frames have gone by. The per-frame copies hold only the views used in that frame and grow and shrink with that count. Encoder API ----------- @@ -173,11 +173,15 @@ Resource limits ``BGFX_CONFIG_DYNAMIC_FRAME_STORAGE`` - Enable dynamic per frame storage. When enabled, storage for render items, binds, blit items and scissor rectangles is allocated in blocks, on first touch, and grows during the frame instead of dropping submissions; ``Init::Limits::numDrawCalls`` is then what is reserved up front rather than a hard limit, and ``Caps::Limits::maxDrawCalls`` always reports ``BGFX_CONFIG_MAX_DRAW_CALLS``. When disabled, all of it is allocated once, up front, at exactly the requested size, indexing has no indirection, and ``Init::Limits::numDrawCalls`` is a hard limit that submissions are dropped past. Default is 1. Disabling trades memory for a small amount of submission throughput; see ``Stats::numDrawCallsPeak`` to size ``numDrawCalls``. -``BGFX_CONFIG_DRAW_CALL_BLOCK`` - Granularity dynamic per frame storage grows by, in items, and the multiple ``Init::Limits::numDrawCalls`` is rounded up to. Must be a power of two. Default is 64. +``BGFX_CONFIG_DRAW_CALL_BLOCK`` - Granularity dynamic per frame storage grows by, in items, and the multiple ``Init::Limits::numDrawCalls`` is rounded up to. Must be a power of two, at least 64. Default is 1024. + +``BGFX_CONFIG_BLIT_BLOCK``, ``BGFX_CONFIG_DEPTH_CONTROL_BLOCK``, ``BGFX_CONFIG_MATRIX_BLOCK``, ``BGFX_CONFIG_RECT_BLOCK``, ``BGFX_CONFIG_VIEW_BLOCK`` - Granularity the per frame blit item, depth control, matrix and scissor rect caches and the view storage grow by. Must be a power of two, at least 64. Default is 64. ``BGFX_CONFIG_MAX_BLIT_ITEMS`` - Maximum number of blit items per frame. Default is 1024. -``BGFX_CONFIG_MAX_VIEWS`` - Maximum number of views. Default is 256. Must be a power of 2. +``BGFX_CONFIG_MAX_VIEWS`` - Number of view ids. Fixed at 4096; view storage is allocated as views are used, so this is only the id range. + +``BGFX_CONFIG_MIN_VIEWS`` - Minimum number of views storage is kept for. Default is 256. Must be at least ``BGFX_CONFIG_VIEW_BLOCK``. ``BGFX_CONFIG_MAX_VIEW_NAME`` - Maximum length of a view name string. Default is 256. diff --git a/examples/09-hdr/hdr.cpp b/examples/09-hdr/hdr.cpp index 74d57b988..af0d3a087 100644 --- a/examples/09-hdr/hdr.cpp +++ b/examples/09-hdr/hdr.cpp @@ -410,7 +410,7 @@ public: m_time += m_speed * deltaTime; - bgfx::ViewId shuffle[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + bgfx::ViewId shuffle[10] = { 300, 301, 302, 303, 304, 305, 306, 307, 308, 309 }; bx::shuffle(&m_rng, shuffle, BX_COUNTOF(shuffle) ); bgfx::ViewId hdrSkybox = shuffle[0]; @@ -499,7 +499,7 @@ public: // Set view and projection matrix for view 0. for (uint8_t ii = 0; ii < BX_COUNTOF(order); ++ii) { - bgfx::setViewTransform(ii, NULL, proj); + bgfx::setViewTransform(order[ii], NULL, proj); } const bx::Vec3 at = { 0.0f, 1.0f, 0.0f }; diff --git a/examples/common/imgui/imgui.cpp b/examples/common/imgui/imgui.cpp index 9464b3651..c2bdf800f 100644 --- a/examples/common/imgui/imgui.cpp +++ b/examples/common/imgui/imgui.cpp @@ -613,7 +613,7 @@ void imguiDestroy() void imguiBeginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, uint16_t _width, uint16_t _height, int _inputChar, bgfx::ViewId _viewId) { - s_ctx.beginFrame(_mx, _my, _button, _scroll, _width, _height, _inputChar, _viewId); + s_ctx.beginFrame(_mx, _my, _button, _scroll, _width, _height, _inputChar, bx::min(_viewId, bgfx::getCaps()->limits.maxViews-1) ); } void imguiEndFrame() diff --git a/examples/common/imgui/imgui.h b/examples/common/imgui/imgui.h index 4fac692af..48e93e700 100644 --- a/examples/common/imgui/imgui.h +++ b/examples/common/imgui/imgui.h @@ -31,7 +31,7 @@ namespace bx { struct AllocatorI; } void imguiCreate(float _fontSize = 18.0f, bx::AllocatorI* _allocator = NULL); void imguiDestroy(); -void imguiBeginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, uint16_t _width, uint16_t _height, int _inputChar = -1, bgfx::ViewId _view = 255); +void imguiBeginFrame(int32_t _mx, int32_t _my, uint8_t _button, int32_t _scroll, uint16_t _width, uint16_t _height, int _inputChar = -1, bgfx::ViewId _view = UINT16_MAX); void imguiEndFrame(); namespace entry { class AppI; } diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index dd12739b8..15d7d2398 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -761,12 +761,20 @@ namespace bgfx /// back; submissions past it are dropped. See /// `Stats::numDrawCallsPeak` to size it. uint32_t numDrawCallPeakFrames; //!< Number of frames the draw-call peak (high-water mark) is observed - /// before unused storage is released. Also used for resource command - /// buffers and uniform buffers. Set to 0 to keep whatever has been - /// allocated for the lifetime of the context. With + /// before unused storage is released. Also used for view storage, + /// resource command buffers and uniform buffers. Set to 0 to keep + /// whatever has been allocated for the lifetime of the context. With /// `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled draw/blit/rect storage /// is not resized; unused uniform and resource command buffer space /// is still released. + uint32_t minViews; //!< Minimum number of views to keep state for. Rounded up to a + /// multiple of 64. This is a reservation, not a limit: a view past it + /// gets storage when it is first set, up to + /// `Caps::Limits::maxViews`, and that storage is released again once + /// the views sharing it are all reset. Per-frame view data is sized + /// by the views used in a frame, see `numDrawCallPeakFrames`. With + /// `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled storage for all views + /// is allocated up front. uint32_t minResourceCbSize; //!< Minimum resource command buffer size. uint32_t maxTransientVbSize; //!< Maximum transient vertex buffer size. uint32_t maxTransientIbSize; //!< Maximum transient index buffer size. @@ -4076,10 +4084,10 @@ namespace bgfx /// /// In graphics debugger view name will appear as: /// - /// "nnnc " - /// ^ ^ ^ - /// | +--- compute (C) - /// +------ view id + /// "nnnnc " + /// ^ ^ ^ + /// | +--- compute (C) + /// +------- view id /// /// @attention C99's equivalent binding is `bgfx_set_view_name`. /// @@ -4283,7 +4291,9 @@ namespace bgfx , const void* _proj ); - /// Post submit view reordering. + /// Post submit view reordering. A view in `_order` that currently renders + /// outside the remapped range swaps places with the view it displaces, so the + /// order stays a permutation of all view ids. /// /// @param[in] _id First view id. /// @param[in] _num Number of views to remap. @@ -4312,7 +4322,7 @@ namespace bgfx , ShadingRate::Enum _shadingRate = ShadingRate::Rate1x1 ); - /// Reset all view settings to default. + /// Reset all view settings to default, including the view name. /// /// @param[in] _id _id View id. /// diff --git a/include/bgfx/c99/bgfx.h b/include/bgfx/c99/bgfx.h index be7f818d9..3145eadd5 100644 --- a/include/bgfx/c99/bgfx.h +++ b/include/bgfx/c99/bgfx.h @@ -858,14 +858,26 @@ typedef struct bgfx_init_limits_s /** * Number of frames the draw-call peak (high-water mark) is observed - * before unused storage is released. Also used for resource command - * buffers and uniform buffers. Set to 0 to keep whatever has been - * allocated for the lifetime of the context. With + * before unused storage is released. Also used for view storage, + * resource command buffers and uniform buffers. Set to 0 to keep + * whatever has been allocated for the lifetime of the context. With * `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled draw/blit/rect storage * is not resized; unused uniform and resource command buffer space * is still released. */ uint32_t numDrawCallPeakFrames; + + /** + * Minimum number of views to keep state for. Rounded up to a + * multiple of 64. This is a reservation, not a limit: a view past it + * gets storage when it is first set, up to + * `Caps::Limits::maxViews`, and that storage is released again once + * the views sharing it are all reset. Per-frame view data is sized + * by the views used in a frame, see `numDrawCallPeakFrames`. With + * `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled storage for all views + * is allocated up front. + */ + uint32_t minViews; uint32_t minResourceCbSize; /** Minimum resource command buffer size. */ uint32_t maxTransientVbSize; /** Maximum transient vertex buffer size. */ uint32_t maxTransientIbSize; /** Maximum transient index buffer size. */ @@ -2834,10 +2846,10 @@ BGFX_C_API void bgfx_set_palette_color_rgba8(uint8_t _index, uint32_t _rgba); * * In graphics debugger view name will appear as: * - * "nnnc " - * ^ ^ ^ - * | +--- compute (C) - * +------ view id + * "nnnnc " + * ^ ^ ^ + * | +--- compute (C) + * +------- view id * * @param[in] _id View id. * @param[in] _name View name. @@ -2986,7 +2998,9 @@ BGFX_C_API void bgfx_set_view_frame_buffer(bgfx_view_id_t _id, bgfx_frame_buffer BGFX_C_API void bgfx_set_view_transform(bgfx_view_id_t _id, const void* _view, const void* _proj); /** - * Post submit view reordering. + * Post submit view reordering. A view in `_order` that currently renders + * outside the remapped range swaps places with the view it displaces, so the + * order stays a permutation of all view ids. * * @param[in] _id First view id. * @param[in] _num Number of views to remap. @@ -3008,7 +3022,7 @@ BGFX_C_API void bgfx_set_view_order(bgfx_view_id_t _id, uint16_t _num, const bgf BGFX_C_API void bgfx_set_view_shading_rate(bgfx_view_id_t _id, bgfx_shading_rate_t _shadingRate); /** - * Reset all view settings to default. + * Reset all view settings to default, including the view name. * * @param[in] _id _id View id. * diff --git a/include/bgfx/defines.h b/include/bgfx/defines.h index a82ef84c9..b6ad8a6f5 100644 --- a/include/bgfx/defines.h +++ b/include/bgfx/defines.h @@ -15,7 +15,7 @@ #ifndef BGFX_DEFINES_H_HEADER_GUARD #define BGFX_DEFINES_H_HEADER_GUARD -#define BGFX_API_VERSION UINT32_C(162) +#define BGFX_API_VERSION UINT32_C(163) /** * Color RGB/alpha/depth write. When it's not specified write will be disabled. diff --git a/scripts/bgfx.idl b/scripts/bgfx.idl index 6ed1a4f62..8bcd12d2d 100644 --- a/scripts/bgfx.idl +++ b/scripts/bgfx.idl @@ -1,7 +1,7 @@ -- vim: syntax=lua -- bgfx interface -version(162) +version(163) typedef "bool" typedef "char" @@ -955,12 +955,20 @@ struct.Limits { ctor, namespace = "Init" } --- back; submissions past it are dropped. See --- `Stats::numDrawCallsPeak` to size it. .numDrawCallPeakFrames "uint32_t" --- Number of frames the draw-call peak (high-water mark) is observed - --- before unused storage is released. Also used for resource command - --- buffers and uniform buffers. Set to 0 to keep whatever has been - --- allocated for the lifetime of the context. With + --- before unused storage is released. Also used for view storage, + --- resource command buffers and uniform buffers. Set to 0 to keep + --- whatever has been allocated for the lifetime of the context. With --- `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled draw/blit/rect storage --- is not resized; unused uniform and resource command buffer space --- is still released. + .minViews "uint32_t" --- Minimum number of views to keep state for. Rounded up to a + --- multiple of 64. This is a reservation, not a limit: a view past it + --- gets storage when it is first set, up to + --- `Caps::Limits::maxViews`, and that storage is released again once + --- the views sharing it are all reset. Per-frame view data is sized + --- by the views used in a frame, see `numDrawCallPeakFrames`. With + --- `BGFX_CONFIG_DYNAMIC_FRAME_STORAGE` disabled storage for all views + --- is allocated up front. .minResourceCbSize "uint32_t" --- Minimum resource command buffer size. .maxTransientVbSize "uint32_t" --- Maximum transient vertex buffer size. .maxTransientIbSize "uint32_t" --- Maximum transient index buffer size. @@ -2470,10 +2478,10 @@ func.setPaletteColor { cname = "set_palette_color_rgba8", section = "Miscellaneo --- --- In graphics debugger view name will appear as: --- ---- "nnnc " ---- ^ ^ ^ ---- | +--- compute (C) ---- +------ view id +--- "nnnnc " +--- ^ ^ ^ +--- | +--- compute (C) +--- +------- view id --- func.setViewName { section = "Views" } "void" @@ -2614,7 +2622,9 @@ func.setViewTransform { section = "Views" } .view "const void*" --- View matrix. .proj "const void*" --- Projection matrix. ---- Post submit view reordering. +--- Post submit view reordering. A view in `_order` that currently renders +--- outside the remapped range swaps places with the view it displaces, so the +--- order stays a permutation of all view ids. func.setViewOrder { section = "Views" } "void" .id "ViewId" --- First view id. @@ -2635,7 +2645,7 @@ func.setViewShadingRate { section = "Views" } .shadingRate "ShadingRate::Enum" --- Shading rate. { default = "ShadingRate::Rate1x1" } ---- Reset all view settings to default. +--- Reset all view settings to default, including the view name. func.resetView { section = "Views" } "void" .id "ViewId" --- _id View id. diff --git a/src/bgfx.cpp b/src/bgfx.cpp index cb8d6b0ed..0232ecc55 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -387,7 +387,6 @@ namespace bgfx bx::AllocatorI* g_allocator = NULL; Caps g_caps; - char g_viewName[BGFX_CONFIG_MAX_VIEWS][BGFX_CONFIG_MAX_VIEW_NAME]; #if BGFX_CONFIG_MULTITHREADED static BX_THREAD_LOCAL uint32_t s_threadIndex(0); @@ -396,6 +395,43 @@ namespace bgfx #endif // BGFX_CONFIG_MULTITHREADED static Context* s_ctx = NULL; + + const char* getViewName(const Frame* _frame, ViewId _view) + { + return s_ctx->m_viewNames.get(_frame->view(_view).m_nameIdx); + } + + void formatViewName(char* _out, const Frame* _frame, ViewId _view, const bx::StringView& _type) + { + _out[0] = _view >= 1000 ? char('0' + (_view/1000)%10) : ' '; + _out[1] = _view >= 100 ? char('0' + (_view/ 100)%10) : ' '; + _out[2] = _view >= 10 ? char('0' + (_view/ 10)%10) : ' '; + _out[3] = char('0' + _view%10); + _out[4] = ' '; + _out[5] = ' '; + _out[6] = ' '; + + bx::strCopy(&_out[BGFX_CONFIG_MAX_VIEW_NAME_RESERVED] + , BGFX_CONFIG_MAX_VIEW_NAME-BGFX_CONFIG_MAX_VIEW_NAME_RESERVED + , getViewName(_frame, _view) + ); + + bx::memCopy(&_out[4], _type.getPtr(), _type.getLength() ); + } + + const View& Frame::view(ViewId _id) const + { + const uint32_t word = _id / 64; + const uint64_t bit = UINT64_C(1) << (_id & 63); + const uint64_t used = m_viewUsed[word]; + + if (0 == (used & bit) ) + { + return s_ctx->m_view.unset(); + } + + return m_view[m_viewUsedOffset[word] + bx::countBits(used & (bit - 1) )]; + } static bool s_renderFrameCalled = false; InternalData g_internalData; PlatformData g_platformData; @@ -1589,7 +1625,7 @@ namespace bgfx m_key.m_view = _id; SortKey::Enum type; - switch (s_ctx->m_view[_id].m_mode) + switch (s_ctx->m_view.get(_id).m_mode) { case ViewMode::Sequential: m_key.m_seq = renderItemIdx; type = SortKey::SortSequence; break; case ViewMode::DepthAscending: m_key.m_depth = _depth; type = SortKey::SortDepth; break; @@ -1717,14 +1753,9 @@ namespace bgfx { BGFX_PROFILER_SCOPE("bgfx/Sort", kColorSubmit); - for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) - { - m_viewOrder[m_viewRemap[ii] ] = ViewId(ii); - } - for (uint32_t ii = 0, num = m_numUsedViews; ii < num; ++ii) { - View& view = m_view[m_usedViews[ii] ]; + View& view = m_view[ii]; Rect rect(0, 0, uint16_t(m_mainSwapChain.width), uint16_t(m_mainSwapChain.height) ); if (isValid(view.m_fbh) ) @@ -2425,12 +2456,12 @@ namespace bgfx for (uint32_t ii = 0; ii < BX_COUNTOF(m_viewRemap); ++ii) { m_viewRemap[ii] = ViewId(ii); + m_viewOrder[ii] = ViewId(ii); } - for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) - { - resetView(ViewId(ii) ); - } + m_view.create(_init.limits.minViews); + m_viewNames.create(); + m_viewObserve = 0; for (uint32_t ii = 0; ii < BX_COUNTOF(m_clearColor); ++ii) { @@ -2487,6 +2518,7 @@ namespace bgfx bx::free(g_allocator, m_encoderStats); m_vertexLayoutRef.shutdown(m_layoutHandle); + m_viewNames.destroy(); m_submit->destroy(); #if BGFX_CONFIG_MULTITHREADED if (m_thread.isRunning() ) @@ -2632,6 +2664,7 @@ namespace bgfx bx::memSet(&g_internalData, 0, sizeof(InternalData) ); s_ctx = NULL; + m_viewNames.destroy(); m_submit->destroy(); if (BX_ENABLED(BGFX_CONFIG_DEBUG) ) @@ -2905,17 +2938,48 @@ namespace bgfx m_submit->m_debugFrameBuffer = m_debugFrameBuffer; m_submit->m_debugTextScale = m_debugTextScale; m_submit->m_perfStats.numViews = 0; - m_submit->reserveViewStats(0 != (m_debug & BGFX_DEBUG_PROFILER) ); - - bx::memCopy(m_submit->m_viewRemap, m_viewRemap, sizeof(m_viewRemap) ); + m_submit->reserveViewStats(0 != (m_debug & BGFX_DEBUG_PROFILER), m_submit->m_numUsedViews); m_uniformCache.frame(m_submit->m_uniformCacheFrame); static_assert(bx::isTriviallyCopyable(), "Must be memcopyiable..."); - for (uint32_t ii = 0, num = m_submit->m_numUsedViews; ii < num; ++ii) + for (uint32_t ww = 0, num = 0; ww < kViewUsedWords; ++ww) { - const ViewId id = m_submit->m_usedViews[ii]; - m_submit->m_view[id] = m_view[id]; + uint64_t bits = m_submit->m_viewUsed[ww]; + + if (0 != bits) + { + const View* src = m_view.find(ww*64); + View* dst = &m_submit->m_view[num]; + + while (0 != bits) + { + const uint32_t bit = bx::countTrailingZeros(bits); + const ViewId id = ViewId(ww*64 + bit); + const ViewId order = m_viewOrder[id]; + bits &= bits - 1; + + *dst++ = NULL != src + ? src[bit] + : m_view.unset() + ; + m_submit->m_viewOrder[id] = order; + m_submit->m_viewRemap[order] = id; + + if (0 == (++num % kViewBlock) ) + { + dst = &m_submit->m_view[num]; + } + } + } + } + + if (0 != m_init.limits.numDrawCallPeakFrames + && ++m_viewObserve >= m_init.limits.numDrawCallPeakFrames) + { + m_view.freeUnset(); + m_viewNames.freeUnused(); + m_viewObserve = 0; } if (m_colorPaletteDirty > 0) @@ -3487,12 +3551,6 @@ namespace bgfx Init init; _cmdbuf.read(init); - // Init reserved part of view name. - for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) - { - bx::snprintf(g_viewName[ii], BGFX_CONFIG_MAX_VIEW_NAME_RESERVED+1, "%3d ", ii); - } - m_renderCtx = rendererCreate(init); m_rendererInitialized = NULL != m_renderCtx; @@ -4049,16 +4107,16 @@ namespace bgfx { BGFX_PROFILER_SCOPE("UpdateViewName", kColorResource); - ViewId id; - _cmdbuf.read(id); + uint16_t idx; + _cmdbuf.read(idx); uint16_t len; _cmdbuf.read(len); const char* name = (const char*)_cmdbuf.skip(len); - bx::strCopy(&g_viewName[id][BGFX_CONFIG_MAX_VIEW_NAME_RESERVED] - , BX_COUNTOF(g_viewName[0])-BGFX_CONFIG_MAX_VIEW_NAME_RESERVED + bx::strCopy(m_viewNames.data(idx) + , ViewNameArena::kNameSize-BGFX_CONFIG_MAX_VIEW_NAME_RESERVED , name ); } @@ -4175,6 +4233,7 @@ namespace bgfx : BGFX_CONFIG_MAX_DRAW_CALLS ) , numDrawCallPeakFrames(60) + , minViews(bx::min(BGFX_CONFIG_MIN_VIEWS, BGFX_CONFIG_MAX_VIEWS) ) , minResourceCbSize(BGFX_CONFIG_MIN_RESOURCE_COMMAND_BUFFER_SIZE) , maxTransientVbSize(BGFX_CONFIG_MAX_TRANSIENT_VERTEX_BUFFER_SIZE) , maxTransientIbSize(BGFX_CONFIG_MAX_TRANSIENT_INDEX_BUFFER_SIZE) @@ -4224,6 +4283,7 @@ namespace bgfx init.limits.maxEncoders = bx::clamp(init.limits.maxEncoders, 1, (0 != BGFX_CONFIG_MULTITHREADED) ? 128 : 1); init.limits.numDrawCalls = alignDrawCalls(bx::max(init.limits.numDrawCalls, kDrawCallBlock) ); + init.limits.minViews = bx::alignUp(bx::clamp(init.limits.minViews, kViewBlock, BGFX_CONFIG_MAX_VIEWS), kViewBlock); init.limits.minResourceCbSize = bx::min(init.limits.minResourceCbSize, BGFX_CONFIG_MIN_RESOURCE_COMMAND_BUFFER_SIZE); struct ErrorState diff --git a/src/bgfx_p.h b/src/bgfx_p.h index d71aeb28d..4fd410600 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -292,12 +292,13 @@ namespace bgfx typedef uint32_t RenderItemCount; #endif // BGFX_CONFIG_MAX_DRAW_CALLS < (64<<10) - static constexpr uint32_t kDrawCallBlock = BGFX_CONFIG_DRAW_CALL_BLOCK; - static constexpr uint16_t kMatrixBlock = 64; - static constexpr uint32_t kBlitBlock = 64; - static constexpr uint32_t kRectBlock = 64; - static constexpr uint32_t kDepthControlBlock = 64; - static constexpr uint32_t kViewUsedWords = bx::alignUp(BGFX_CONFIG_MAX_VIEWS, 64)/64; + static constexpr uint32_t kBlitBlock = BGFX_CONFIG_BLIT_BLOCK; + static constexpr uint32_t kDepthControlBlock = BGFX_CONFIG_DEPTH_CONTROL_BLOCK; + static constexpr uint32_t kDrawCallBlock = BGFX_CONFIG_DRAW_CALL_BLOCK; + static constexpr uint32_t kMatrixBlock = BGFX_CONFIG_MATRIX_BLOCK; + static constexpr uint32_t kRectBlock = BGFX_CONFIG_RECT_BLOCK; + static constexpr uint32_t kViewBlock = BGFX_CONFIG_VIEW_BLOCK; + static constexpr uint32_t kViewUsedWords = bx::alignUp(BGFX_CONFIG_MAX_VIEWS, 64)/64; inline uint32_t alignDrawCalls(uint32_t _num) { @@ -667,7 +668,9 @@ namespace bgfx extern CallbackI* g_callback; extern bx::AllocatorI* g_allocator; extern Caps g_caps; - extern char g_viewName[BGFX_CONFIG_MAX_VIEWS][BGFX_CONFIG_MAX_VIEW_NAME]; + struct Frame; + void formatViewName(char* _out, const Frame* _frame, ViewId _view, const bx::StringView& _type); + const char* getViewName(const Frame* _frame, ViewId _view); struct ProfilerScope { @@ -3168,10 +3171,11 @@ namespace bgfx { void reset() { + bx::memSet(this, 0, sizeof(View) ); + setRect(0, 0, 1, 1); setScissor(0, 0, 0, 0); setClear(BGFX_CLEAR_NONE, 0, 0.0f, 0); - setMode(ViewMode::Default); setShadingRate(ShadingRate::Rate1x1); setFrameBuffer(BGFX_INVALID_HANDLE); setTransform(NULL, NULL); @@ -3221,11 +3225,6 @@ namespace bgfx m_clear.set(_flags, _depth, _stencil, _0, _1, _2, _3, _4, _5, _6, _7); } - void setMode(ViewMode::Enum _mode) - { - m_mode = uint8_t(_mode); - } - void setShadingRate(ShadingRate::Enum _shadingRate) { m_shadingRate = uint8_t(_shadingRate); @@ -3269,14 +3268,356 @@ namespace bgfx Matrix4 m_view; Matrix4 m_proj; FrameBufferHandle m_fbh; - uint8_t m_mode; + uint16_t m_nameIdx; uint8_t m_shadingRate; + uint8_t m_mode; float m_minDepth = 0.0f; float m_maxDepth = 1.0f; DepthControl m_depthBias; uint32_t m_sampleMask; }; + class ViewArena + { + public: + ~ViewArena() + { + destroy(); + } + +#if BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + static constexpr uint32_t kBlockMask = kViewBlock - 1; + static constexpr uint32_t kNumBlocks = bx::alignUp(BGFX_CONFIG_MAX_VIEWS, kViewBlock)/kViewBlock; + + ViewArena() + : m_reserved(NULL) + , m_numReservedBlocks(0) + { + bx::memSet(m_block, 0, sizeof(m_block) ); + m_default.reset(); + } + + void create(uint32_t _numReserved) + { + destroy(); + + m_numReservedBlocks = bx::min( (_numReserved + kBlockMask)/kViewBlock, kNumBlocks); + + if (0 < m_numReservedBlocks) + { + m_reserved = alloc(m_numReservedBlocks*kViewBlock); + + for (uint32_t ii = 0; ii < m_numReservedBlocks; ++ii) + { + m_block[ii] = m_reserved + ii*kViewBlock; + } + } + } + + void destroy() + { + for (uint32_t ii = m_numReservedBlocks; ii < kNumBlocks; ++ii) + { + freeBlock(ii); + } + + if (NULL != m_reserved) + { + bx::free(g_allocator, m_reserved, BX_ALIGNOF(View) ); + m_reserved = NULL; + } + + bx::memSet(m_block, 0, sizeof(m_block) ); + m_numReservedBlocks = 0; + } + + BX_FORCE_INLINE View& operator[](uint32_t _id) + { + const uint32_t blockIdx = _id / kViewBlock; + + View* block = load(blockIdx); + + if (NULL == block) + { + block = allocBlock(blockIdx); + } + + return block[_id & kBlockMask]; + } + + BX_FORCE_INLINE View* find(uint32_t _id) + { + View* block = load(_id / kViewBlock); + + return NULL != block + ? &block[_id & kBlockMask] + : NULL + ; + } + + BX_FORCE_INLINE const View& get(uint32_t _id) const + { + const View* block = load(_id / kViewBlock); + + return NULL != block + ? block[_id & kBlockMask] + : m_default + ; + } + + BX_FORCE_INLINE const View& unset() const + { + return m_default; + } + + void freeUnset() + { + for (uint32_t ii = m_numReservedBlocks; ii < kNumBlocks; ++ii) + { + const View* block = m_block[ii]; + + if (NULL != block) + { + bool unset = true; + + for (uint32_t jj = 0; jj < kViewBlock && unset; ++jj) + { + unset = 0 == bx::memCmp(&block[jj], &m_default, sizeof(View) ); + } + + if (unset) + { + freeBlock(ii); + } + } + } + } + + private: + static View* alloc(uint32_t _num) + { + View* view = (View*)bx::alloc(g_allocator, sizeof(View)*_num, BX_ALIGNOF(View) ); + + for (uint32_t ii = 0; ii < _num; ++ii) + { + view[ii].reset(); + } + + return view; + } + + BX_FORCE_INLINE View* load(uint32_t _blockIdx) const + { + return *(View* volatile*)&m_block[_blockIdx]; + } + + BX_NO_INLINE View* allocBlock(uint32_t _blockIdx) + { + bx::MutexScope lock(m_lock); + + View* block = m_block[_blockIdx]; + + if (NULL == block) + { + block = alloc(kViewBlock); + + bx::atomicExchangePtr( (void**)&m_block[_blockIdx], block); + } + + return block; + } + + void freeBlock(uint32_t _blockIdx) + { + if (NULL != m_block[_blockIdx]) + { + bx::free(g_allocator, m_block[_blockIdx], BX_ALIGNOF(View) ); + m_block[_blockIdx] = NULL; + } + } + + View* m_block[kNumBlocks]; + View* m_reserved; + uint32_t m_numReservedBlocks; + View m_default; + bx::Mutex m_lock; +#else + ViewArena() + { + create(BGFX_CONFIG_MAX_VIEWS); + m_default.reset(); + } + + void create(uint32_t /*_numReserved*/) + { + for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) + { + m_view[ii].reset(); + } + } + + void destroy() + { + } + + BX_FORCE_INLINE View& operator[](uint32_t _id) + { + return m_view[_id]; + } + + BX_FORCE_INLINE View* find(uint32_t _id) + { + return &m_view[_id]; + } + + BX_FORCE_INLINE const View& get(uint32_t _id) const + { + return m_view[_id]; + } + + BX_FORCE_INLINE const View& unset() const + { + return m_default; + } + + void freeUnset() + { + } + + private: + View m_view[BGFX_CONFIG_MAX_VIEWS]; + View m_default; +#endif // BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + }; + + class ViewNameArena + { + public: + static constexpr uint32_t kBlock = 64; + static constexpr uint32_t kBlockMask = kBlock - 1; + static constexpr uint32_t kNumNames = BGFX_CONFIG_MAX_VIEWS + 1; + static constexpr uint32_t kNumBlocks = (kNumNames + kBlockMask)/kBlock; + static constexpr uint32_t kNameSize = BGFX_CONFIG_MAX_VIEW_NAME; + + void create() + { + bx::memSet(m_used, 0, sizeof(m_used) ); + bx::memSet(m_touched, 0, sizeof(m_touched) ); + + m_used[0] = 1; + } + + void destroy() + { +#if BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + for (uint32_t ii = 0; ii < kNumBlocks; ++ii) + { + freeBlock(ii); + } +#endif // BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + } + + uint16_t alloc() + { + for (uint32_t blockIdx = 0; blockIdx < kNumBlocks; ++blockIdx) + { + const uint64_t avail = ~m_used[blockIdx]; + + if (0 != avail) + { + const uint32_t bit = bx::countTrailingZeros(avail); + const uint32_t idx = blockIdx*kBlock + bit; + + if (idx >= kNumNames) + { + break; + } + +#if BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + if (NULL == m_block[blockIdx]) + { + char* block = (char*)bx::alloc(g_allocator, kBlock*kNameSize); + bx::memSet(block, 0, kBlock*kNameSize); + + bx::atomicExchangePtr( (void**)&m_block[blockIdx], block); + } +#endif // BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + + m_used[blockIdx] |= UINT64_C(1) << bit; + m_touched[blockIdx] = true; + + return uint16_t(idx); + } + } + + BX_ASSERT(false, "Out of view names."); + return 0; + } + + void free(uint16_t _idx) + { + m_used[_idx / kBlock] &= ~(UINT64_C(1) << (_idx & kBlockMask) ); + } + + const char* get(uint16_t _idx) const + { +#if BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + const char* block = *(char* volatile*)&m_block[_idx / kBlock]; + + if (NULL == block) + { + return ""; + } +#else + const char* block = m_name[_idx / kBlock]; +#endif // BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + + return &block[(_idx & kBlockMask)*kNameSize]; + } + + char* data(uint16_t _idx) + { + BX_ASSERT(0 != _idx, "View name 0 is the unset name."); + + return const_cast(get(_idx) ); + } + + void freeUnused() + { + for (uint32_t ii = 1; ii < kNumBlocks; ++ii) + { + if (0 == m_used[ii] + && !m_touched[ii]) + { +#if BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + freeBlock(ii); +#endif // BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + } + + m_touched[ii] = false; + } + } + + private: +#if BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + void freeBlock(uint32_t _blockIdx) + { + if (NULL != m_block[_blockIdx]) + { + bx::free(g_allocator, m_block[_blockIdx]); + m_block[_blockIdx] = NULL; + } + } + + char* m_block[kNumBlocks] = {}; +#else + char m_name[kNumBlocks][kBlock*kNameSize] = {}; +#endif // BGFX_CONFIG_DYNAMIC_FRAME_STORAGE + + uint64_t m_used[kNumBlocks]; + bool m_touched[kNumBlocks]; + }; + struct UniformCacheKey { using KeyT = uint64_t; @@ -3491,6 +3832,7 @@ namespace bgfx , m_observe(0) , m_numPeakFrames(0) , m_viewStats(NULL) + , m_numViewStats(0) , m_waitSubmit(0) , m_waitRender(0) , m_frameNum(0) @@ -3498,11 +3840,13 @@ namespace bgfx , m_flush(false) , m_needBindDedup(false) , m_numUsedViews(0) + , m_peakViews(0) { m_numRenderItems = 0; m_numRenderBinds = 0; bx::memSet(m_occlusion, 0xff, sizeof(m_occlusion) ); bx::memSet(m_viewUsed, 0, sizeof(m_viewUsed) ); + bx::memSet(m_viewUsedOffset, 0, sizeof(m_viewUsedOffset) ); m_perfStats.viewStats = m_viewStats; } @@ -3527,6 +3871,7 @@ namespace bgfx m_renderItem.create(reserved, num); m_renderBind.create(reserved, num); + m_view.create(kViewBlock, BGFX_CONFIG_MAX_VIEWS); m_blitItem.create(0, BGFX_CONFIG_MAX_BLIT_ITEMS); reserveBlitKeys(0); @@ -3548,16 +3893,19 @@ namespace bgfx m_blitKeys[_num] = 0; } - void reserveViewStats(bool _enable) + void reserveViewStats(bool _enable, uint32_t _num) { if (!_enable) { bx::free(g_allocator, m_viewStats); m_viewStats = NULL; + m_numViewStats = 0; } - else if (NULL == m_viewStats) + else if (m_numViewStats < _num) { - m_viewStats = (ViewStats*)bx::alloc(g_allocator, sizeof(ViewStats)*BGFX_CONFIG_MAX_VIEWS); + bx::free(g_allocator, m_viewStats); + m_numViewStats = bx::alignUp(_num, kViewBlock); + m_viewStats = (ViewStats*)bx::alloc(g_allocator, sizeof(ViewStats)*m_numViewStats); } m_perfStats.viewStats = m_viewStats; @@ -3573,8 +3921,9 @@ namespace bgfx m_blitKeys = NULL; m_blitKeysCapacity = 0; - reserveViewStats(false); + reserveViewStats(false, 0); + m_view.destroy(); m_renderItem.destroy(); m_renderBind.destroy(); m_blitItem.destroy(); @@ -3600,6 +3949,7 @@ namespace bgfx m_peakBlit = bx::max(m_peakBlit, m_numBlitItems); m_peakRect = bx::max(m_peakRect, m_frameCache.m_rectCache.m_num); m_peakDepthBias = bx::max(m_peakDepthBias, m_frameCache.m_depthBiasCache.m_num); + m_peakViews = bx::max(m_peakViews, m_numUsedViews); if (++m_observe >= m_numPeakFrames) { @@ -3610,6 +3960,7 @@ namespace bgfx m_blitItem.shrink(m_peakBlit + 1 + kBlitBlock); m_frameCache.m_rectCache.shrink(m_peakRect + 1 + kRectBlock); m_frameCache.m_depthBiasCache.shrink(m_peakDepthBias + 1 + kDepthControlBlock); + m_view.shrink(m_peakViews + kViewBlock); m_cmdPre.shrink(); m_cmdPost.shrink(); @@ -3625,6 +3976,7 @@ namespace bgfx m_peakBlit = 0; m_peakRect = 0; m_peakDepthBias = 0; + m_peakViews = 0; m_observe = 0; } } @@ -3718,14 +4070,8 @@ namespace bgfx for (uint32_t ww = 0; ww < kViewUsedWords; ++ww) { - uint64_t bits = m_viewUsed[ww]; - - while (0 != bits) - { - const uint8_t bit = bx::countTrailingZeros(bits); - m_usedViews[num++] = ViewId(ww*64 + bit); - bits &= bits - 1; - } + m_viewUsedOffset[ww] = num; + num += uint16_t(bx::countBits(m_viewUsed[ww]) ); } m_numUsedViews = num; @@ -3833,8 +4179,9 @@ namespace bgfx ViewId m_viewRemap[BGFX_CONFIG_MAX_VIEWS]; ViewId m_viewOrder[BGFX_CONFIG_MAX_VIEWS+1]; //!< Inverse of m_viewRemap. float m_colorPalette[BGFX_CONFIG_MAX_COLOR_PALETTE][4]; + FrameArenaT m_view; - View m_view[BGFX_CONFIG_MAX_VIEWS]; + const View& view(ViewId _id) const; int32_t m_occlusion[BGFX_CONFIG_MAX_OCCLUSION_QUERIES]; @@ -3952,6 +4299,7 @@ namespace bgfx Stats m_perfStats; ViewStats* m_viewStats; + uint32_t m_numViewStats; int64_t m_waitSubmit; int64_t m_waitRender; @@ -3963,8 +4311,9 @@ namespace bgfx bool m_needBindDedup; uint64_t m_viewUsed[kViewUsedWords]; - ViewId m_usedViews[BGFX_CONFIG_MAX_VIEWS]; + uint16_t m_viewUsedOffset[kViewUsedWords]; uint16_t m_numUsedViews; + uint32_t m_peakViews; }; BX_ALIGN_DECL_CACHE_LINE(struct) EncoderImpl @@ -5430,7 +5779,12 @@ namespace bgfx for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) { - m_view[ii].setFrameBuffer(BGFX_INVALID_HANDLE); + View* view = m_view.find(ii); + + if (NULL != view) + { + view->setFrameBuffer(BGFX_INVALID_HANDLE); + } } for (uint16_t ii = 0, num = m_textureHandle.getNumHandles(); ii < num; ++ii) @@ -7702,8 +8056,15 @@ namespace bgfx { BGFX_MUTEX_SCOPE(m_resourceApiLock); + View& view = m_view[_id]; + + if (0 == view.m_nameIdx) + { + view.m_nameIdx = m_viewNames.alloc(); + } + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::UpdateViewName); - cmdbuf.write(_id); + cmdbuf.write(view.m_nameIdx); cmdbuf.write(_name); } @@ -7749,7 +8110,7 @@ namespace bgfx BGFX_API_FUNC(void setViewMode(ViewId _id, ViewMode::Enum _mode) ) { - m_view[_id].setMode(_mode); + m_view[_id].m_mode = uint8_t(_mode); } BGFX_API_FUNC(void setViewFrameBuffer(ViewId _id, FrameBufferHandle _handle) ) @@ -7766,17 +8127,21 @@ namespace bgfx BGFX_API_FUNC(void setViewOrder(ViewId _id, uint16_t _num, const ViewId* _order) ) { const uint32_t num = bx::min(_id + _num, BGFX_CONFIG_MAX_VIEWS) - _id; - if (NULL == _order) + + for (uint32_t ii = 0; ii < num; ++ii) { - for (uint32_t ii = 0; ii < num; ++ii) - { - ViewId id = ViewId(ii+_id); - m_viewRemap[id] = id; - } - } - else - { - bx::memCopy(&m_viewRemap[_id], _order, num*sizeof(ViewId) ); + const ViewId pos = ViewId(ii+_id); + const ViewId id = NULL != _order ? _order[ii] : pos; + + BX_ASSERT(id < BGFX_CONFIG_MAX_VIEWS, "Invalid view id: %d", id); + + const ViewId prevPos = m_viewOrder[id]; + const ViewId prevId = m_viewRemap[pos]; + + m_viewRemap[pos] = id; + m_viewOrder[id] = pos; + m_viewRemap[prevPos] = prevId; + m_viewOrder[prevId] = prevPos; } } @@ -7792,7 +8157,19 @@ namespace bgfx BGFX_API_FUNC(void resetView(ViewId _id) ) { - m_view[_id].reset(); + View* view = m_view.find(_id); + + if (NULL != view) + { + if (0 != view->m_nameIdx) + { + BGFX_MUTEX_SCOPE(m_resourceApiLock); + m_viewNames.free(view->m_nameIdx); + } + + view->reset(); + } + m_uniformCache.invalidate(_id); } @@ -7998,7 +8375,10 @@ namespace bgfx VertexLayoutRef m_vertexLayoutRef; ViewId m_viewRemap[BGFX_CONFIG_MAX_VIEWS]; - View m_view[BGFX_CONFIG_MAX_VIEWS]; + ViewId m_viewOrder[BGFX_CONFIG_MAX_VIEWS]; + ViewArena m_view; + ViewNameArena m_viewNames; + uint32_t m_viewObserve; UniformCache m_uniformCache; diff --git a/src/config.h b/src/config.h index 82b76313f..b8c9829ca 100644 --- a/src/config.h +++ b/src/config.h @@ -311,10 +311,46 @@ /// Granularity dynamic per frame storage grows by, in items. Reserving a /// multiple of it up front keeps growing off the common path. Must be power of -/// two. Default is 1024. +/// two, at least 64. Default is 1024. #ifndef BGFX_CONFIG_DRAW_CALL_BLOCK # define BGFX_CONFIG_DRAW_CALL_BLOCK 1024 #endif // BGFX_CONFIG_DRAW_CALL_BLOCK +static_assert(bx::isPowerOf2(BGFX_CONFIG_DRAW_CALL_BLOCK) && 64 <= BGFX_CONFIG_DRAW_CALL_BLOCK, "BGFX_CONFIG_DRAW_CALL_BLOCK must be power of two, at least 64."); + +/// Granularity per frame blit item storage grows by. Must be power of two, at +/// least 64. Default is 64. +#ifndef BGFX_CONFIG_BLIT_BLOCK +# define BGFX_CONFIG_BLIT_BLOCK 64 +#endif // BGFX_CONFIG_BLIT_BLOCK +static_assert(bx::isPowerOf2(BGFX_CONFIG_BLIT_BLOCK) && 64 <= BGFX_CONFIG_BLIT_BLOCK, "BGFX_CONFIG_BLIT_BLOCK must be power of two, at least 64."); + +/// Granularity per frame depth control cache grows by. Must be power of two, +/// at least 64. Default is 64. +#ifndef BGFX_CONFIG_DEPTH_CONTROL_BLOCK +# define BGFX_CONFIG_DEPTH_CONTROL_BLOCK 64 +#endif // BGFX_CONFIG_DEPTH_CONTROL_BLOCK +static_assert(bx::isPowerOf2(BGFX_CONFIG_DEPTH_CONTROL_BLOCK) && 64 <= BGFX_CONFIG_DEPTH_CONTROL_BLOCK, "BGFX_CONFIG_DEPTH_CONTROL_BLOCK must be power of two, at least 64."); + +/// Granularity per frame transform matrix cache grows by. Must be power of +/// two, at least 64. Default is 64. +#ifndef BGFX_CONFIG_MATRIX_BLOCK +# define BGFX_CONFIG_MATRIX_BLOCK 64 +#endif // BGFX_CONFIG_MATRIX_BLOCK +static_assert(bx::isPowerOf2(BGFX_CONFIG_MATRIX_BLOCK) && 64 <= BGFX_CONFIG_MATRIX_BLOCK, "BGFX_CONFIG_MATRIX_BLOCK must be power of two, at least 64."); + +/// Granularity per frame scissor rectangle cache grows by. Must be power of +/// two, at least 64. Default is 64. +#ifndef BGFX_CONFIG_RECT_BLOCK +# define BGFX_CONFIG_RECT_BLOCK 64 +#endif // BGFX_CONFIG_RECT_BLOCK +static_assert(bx::isPowerOf2(BGFX_CONFIG_RECT_BLOCK) && 64 <= BGFX_CONFIG_RECT_BLOCK, "BGFX_CONFIG_RECT_BLOCK must be power of two, at least 64."); + +/// Granularity view storage grows by, in views. Must be power of two, at least +/// 64. Default is 64. +#ifndef BGFX_CONFIG_VIEW_BLOCK +# define BGFX_CONFIG_VIEW_BLOCK 64 +#endif // BGFX_CONFIG_VIEW_BLOCK +static_assert(bx::isPowerOf2(BGFX_CONFIG_VIEW_BLOCK) && 64 <= BGFX_CONFIG_VIEW_BLOCK, "BGFX_CONFIG_VIEW_BLOCK must be power of two, at least 64."); /// Maximum number of blit items per frame. /// @@ -385,14 +421,20 @@ #define BGFX_CONFIG_MAX_PROGRAMS (1< + class TimerResultT + { + public: + TimerResultT() + : m_result(NULL) + , m_num(0) + { + m_frame.reset(); + } + + ~TimerResultT() + { + bx::free(g_allocator, m_result); + } + + void reset() + { + for (uint32_t ii = 0; ii < m_num; ++ii) + { + m_result[ii].reset(); + } + + m_frame.reset(); + } + + void resetPending() + { + for (uint32_t ii = 0; ii < m_num; ++ii) + { + m_result[ii].m_pending = 0; + } + + m_frame.m_pending = 0; + } + + ResultT& operator[](uint32_t _idx) + { + if (BGFX_CONFIG_MAX_VIEWS == _idx) + { + return m_frame; + } + + if (_idx >= m_num) + { + grow(_idx + 1); + } + + return m_result[_idx]; + } + + private: + BX_NO_INLINE void grow(uint32_t _num) + { + const uint32_t num = bx::alignUp(_num, kTimerQueryBlock); + + ResultT* result = (ResultT*)bx::alloc(g_allocator, sizeof(ResultT)*num); + bx::memCopy(result, m_result, sizeof(ResultT)*m_num); + + for (uint32_t ii = m_num; ii < num; ++ii) + { + result[ii].reset(); + } + + bx::free(g_allocator, m_result); + m_result = result; + m_num = num; + } + + ResultT* m_result; + uint32_t m_num; + ResultT m_frame; + }; + struct BlitState { BlitState(const Frame* _frame) @@ -134,21 +205,19 @@ namespace bgfx m_invProjCached = UINT16_MAX; m_invViewProjCached = UINT16_MAX; - m_view = m_viewTmp; + BX_UNUSED(_frame); + } - for (uint32_t ii = 0, num = _frame->m_numUsedViews; ii < num; ++ii) - { - const uint16_t view = _frame->m_usedViews[ii]; - bx::memCopy(&m_view[view].un.f4x4, &_frame->m_view[view].m_view.un.f4x4, sizeof(Matrix4) ); - bx::float4x4_mul(&m_viewProj[view].un.f4x4 - , &m_view[view].un.f4x4 - , &_frame->m_view[view].m_proj.un.f4x4 - ); - } + BX_NO_INLINE void setView(const View& _renderView) + { + bx::float4x4_mul(&m_viewProj.un.f4x4 + , &_renderView.m_view.un.f4x4 + , &_renderView.m_proj.un.f4x4 + ); } template - void setPredefined(RendererContext* _renderer, uint16_t _view, const Program& _program, const Frame* _frame, const Draw& _draw) + void setPredefined(RendererContext* _renderer, uint16_t _view, const View& _renderView, const Program& _program, const Frame* _frame, const Draw& _draw) { const FrameCache& frameCache = _frame->m_frameCache; @@ -181,8 +250,8 @@ namespace bgfx frect[1] = 1.0f/float(m_rect.m_height); // .zw = the view's viewport depth range [minDepth, maxDepth], for // shaders that clamp a written depth (WebGPU @builtin(frag_depth)). - frect[2] = _frame->m_view[_view].m_minDepth; - frect[3] = _frame->m_view[_view].m_maxDepth; + frect[2] = _renderView.m_minDepth; + frect[3] = _renderView.m_maxDepth; _renderer->setShaderUniform4f(flags , predefined.m_loc @@ -196,7 +265,7 @@ namespace bgfx { _renderer->setShaderUniform4x4f(flags , predefined.m_loc - , m_view[_view].un.val + , _renderView.m_view.un.val , bx::min(mtxRegs, predefined.m_count) ); } @@ -208,7 +277,7 @@ namespace bgfx { m_invViewCached = _view; bx::float4x4_inverse(&m_invView.un.f4x4 - , &m_view[_view].un.f4x4 + , &_renderView.m_view.un.f4x4 ); } @@ -224,7 +293,7 @@ namespace bgfx { _renderer->setShaderUniform4x4f(flags , predefined.m_loc - , _frame->m_view[_view].m_proj.un.val + , _renderView.m_proj.un.val , bx::min(mtxRegs, predefined.m_count) ); } @@ -236,7 +305,7 @@ namespace bgfx { m_invProjCached = _view; bx::float4x4_inverse(&m_invProj.un.f4x4 - , &_frame->m_view[_view].m_proj.un.f4x4 + , &_renderView.m_proj.un.f4x4 ); } @@ -252,7 +321,7 @@ namespace bgfx { _renderer->setShaderUniform4x4f(flags , predefined.m_loc - , m_viewProj[_view].un.val + , m_viewProj.un.val , bx::min(mtxRegs, predefined.m_count) ); } @@ -264,7 +333,7 @@ namespace bgfx { m_invViewProjCached = _view; bx::float4x4_inverse(&m_invViewProj.un.f4x4 - , &m_viewProj[_view].un.f4x4 + , &m_viewProj.un.f4x4 ); } @@ -293,7 +362,7 @@ namespace bgfx const Matrix4& model = frameCache.m_matrixCache.at(_draw.m_startMatrix); bx::model4x4_mul(&modelView.un.f4x4 , &model.un.f4x4 - , &m_view[_view].un.f4x4 + , &_renderView.m_view.un.f4x4 ); _renderer->setShaderUniform4x4f(flags , predefined.m_loc @@ -310,7 +379,7 @@ namespace bgfx const Matrix4& model = frameCache.m_matrixCache.at(_draw.m_startMatrix); bx::model4x4_mul(&modelView.un.f4x4 , &model.un.f4x4 - , &m_view[_view].un.f4x4 + , &_renderView.m_view.un.f4x4 ); bx::float4x4_inverse(&invModelView.un.f4x4 , &modelView.un.f4x4 @@ -329,7 +398,7 @@ namespace bgfx const Matrix4& model = frameCache.m_matrixCache.at(_draw.m_startMatrix); bx::model4x4_mul_viewproj4x4(&modelViewProj.un.f4x4 , &model.un.f4x4 - , &m_viewProj[_view].un.f4x4 + , &m_viewProj.un.f4x4 ); _renderer->setShaderUniform4x4f(flags , predefined.m_loc @@ -373,10 +442,8 @@ namespace bgfx } } - Matrix4 m_viewTmp[BGFX_CONFIG_MAX_VIEWS]; - Matrix4 m_viewProj[BGFX_CONFIG_MAX_VIEWS]; - Matrix4* m_view; Rect m_rect; + Matrix4 m_viewProj; Matrix4 m_invView; Matrix4 m_invProj; Matrix4 m_invViewProj; @@ -883,7 +950,7 @@ namespace bgfx viewStats.view = ViewId(_view); bx::strCopy(viewStats.name , BGFX_CONFIG_MAX_VIEW_NAME - , &g_viewName[_view][BGFX_CONFIG_MAX_VIEW_NAME_RESERVED] + , getViewName(m_frame, _view) ); } } diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 8cbd8f7ae..f6bc7fc3f 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -12,13 +12,13 @@ namespace bgfx { namespace d3d11 { - inline const wchar_t* toViewNameW(wchar_t* _out, ViewId _view) + inline const wchar_t* toViewNameW(wchar_t* _out, const char* _viewName) { - size_t len = mbstowcs(_out, g_viewName[_view], BGFX_CONFIG_MAX_VIEW_NAME-1); + size_t len = mbstowcs(_out, _viewName, BGFX_CONFIG_MAX_VIEW_NAME-1); if (size_t(-1) == len) { - len = mbstowcs(_out, g_viewName[_view], BGFX_CONFIG_MAX_VIEW_NAME_RESERVED); + len = mbstowcs(_out, _viewName, BGFX_CONFIG_MAX_VIEW_NAME_RESERVED); } _out[size_t(-1) == len ? 0 : len] = L'\0'; @@ -6278,11 +6278,7 @@ namespace bgfx { namespace d3d11 { create(0, m_control.getSize() ); - for (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii) - { - Result& result = m_result[ii]; - result.reset(); - } + m_result.reset(); m_control.reset(); } @@ -6926,6 +6922,8 @@ namespace bgfx { namespace d3d11 ProgramHandle currentProgram = BGFX_INVALID_HANDLE; SortKey key; uint16_t view = UINT16_MAX; + const View* renderView = &_render->view(0); + char viewName[BGFX_CONFIG_MAX_VIEW_NAME] = ""; FrameBufferHandle fbh = { BGFX_CONFIG_MAX_FRAME_BUFFERS }; UniformCacheState ucs(_render); @@ -6966,7 +6964,7 @@ namespace bgfx { namespace d3d11 // if we don't do this we'll only see one frame of output and then nothing setFrameBuffer(BGFX_INVALID_HANDLE, true, false); - viewState.m_rect = _render->m_view[0].m_rect; + viewState.m_rect = _render->view(0).m_rect; int32_t numItems = _render->m_numRenderItems; for (int32_t item = 0; item < numItems;) @@ -6988,6 +6986,8 @@ namespace bgfx { namespace d3d11 if (viewChanged) { view = key.m_view; + renderView = &_render->view(view); + viewState.setView(*renderView); currentProgram = BGFX_INVALID_HANDLE; if (item > 1) @@ -6996,18 +6996,18 @@ namespace bgfx { namespace d3d11 } BGFX_D3D11_PROFILER_END(); - setViewType(view, " "); + formatViewName(viewName, _render, view, " "); BGFX_D3D11_PROFILER_BEGIN(view, kColorView); profiler.begin(view); - resolveFrameBuffer(_render->m_view[view].m_fbh); + resolveFrameBuffer(renderView->m_fbh); submitUniformCache(ucs, view); submitBlit(bs, view); - if (_render->m_view[view].m_fbh.idx != fbh.idx) + if (renderView->m_fbh.idx != fbh.idx) { - fbh = _render->m_view[view].m_fbh; + fbh = renderView->m_fbh; setFrameBuffer(fbh); stateMask = isValid(fbh) @@ -7016,10 +7016,10 @@ namespace bgfx { namespace d3d11 ; } - viewState.m_rect = _render->m_view[view].m_rect; - const Rect& clippedRect = _render->m_view[view].m_clippedRect; + viewState.m_rect = renderView->m_rect; + const Rect& clippedRect = renderView->m_clippedRect; - const Rect& scissorRect = _render->m_view[view].m_scissor; + const Rect& scissorRect = renderView->m_scissor; viewHasScissor = !scissorRect.isZero(); viewScissorRect = viewHasScissor ? scissorRect : clippedRect; @@ -7028,10 +7028,10 @@ namespace bgfx { namespace d3d11 vp.TopLeftY = viewState.m_rect.m_y; vp.Width = viewState.m_rect.m_width; vp.Height = viewState.m_rect.m_height; - vp.MinDepth = _render->m_view[view].m_minDepth; - vp.MaxDepth = _render->m_view[view].m_maxDepth; + vp.MinDepth = renderView->m_minDepth; + vp.MaxDepth = renderView->m_maxDepth; deviceCtx->RSSetViewports(1, &vp); - Clear& clr = _render->m_view[view].m_clear; + const Clear& clr = renderView->m_clear; if (BGFX_CLEAR_NONE != (clr.m_flags & BGFX_CLEAR_MASK) ) { @@ -7046,7 +7046,7 @@ namespace bgfx { namespace d3d11 { wasCompute = true; - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_D3D11_PROFILER_END(); BGFX_D3D11_PROFILER_BEGIN(view, kColorCompute); @@ -7093,7 +7093,7 @@ namespace bgfx { namespace d3d11 } } - viewState.setPredefined<4>(this, view, program, _render, compute); + viewState.setPredefined<4>(this, view, *renderView, program, _render, compute); if (constantsChanged || program.m_numPredefined > 0) @@ -7218,7 +7218,7 @@ namespace bgfx { namespace d3d11 if (wasCompute) { - setViewType(view, " "); + setViewType(viewName, " "); BGFX_D3D11_PROFILER_END(); BGFX_D3D11_PROFILER_BEGIN(view, kColorDraw); @@ -7253,7 +7253,7 @@ namespace bgfx { namespace d3d11 } const uint64_t newFlags = draw.m_stateFlags & stateMask; - const uint32_t sampleMask = _render->m_view[view].m_sampleMask & draw.m_sampleMask; + const uint32_t sampleMask = renderView->m_sampleMask & draw.m_sampleMask; uint64_t changedFlags = currentState.m_stateFlags ^ newFlags; changedFlags |= currentState.m_rgba != draw.m_rgba ? BGFX_D3D11_BLEND_STATE_MASK : 0; changedFlags |= currentState.m_sampleMask != sampleMask ? BGFX_D3D11_BLEND_STATE_MASK : 0; @@ -7295,7 +7295,7 @@ namespace bgfx { namespace d3d11 // tracked index. const DepthControl& depthBias = (UINT16_MAX != draw.m_depthBias) ? _render->m_frameCache.m_depthBiasCache.m_cache[draw.m_depthBias] - : _render->m_view[view].m_depthBias; + : renderView->m_depthBias; const bool depthBiasChanged = currentState.m_depthBias != draw.m_depthBias; currentState.m_depthBias = draw.m_depthBias; @@ -7445,7 +7445,7 @@ namespace bgfx { namespace d3d11 } } - viewState.setPredefined<4>(this, view, program, _render, draw); + viewState.setPredefined<4>(this, view, *renderView, program, _render, draw); if (constantsChanged || program.m_numPredefined > 0) @@ -7809,7 +7809,7 @@ namespace bgfx { namespace d3d11 if (wasCompute) { - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_D3D11_PROFILER_END(); BGFX_D3D11_PROFILER_BEGIN(view, kColorCompute); diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index 37354111b..368684fb8 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -55,14 +55,14 @@ BX_PRAGMA_DIAGNOSTIC_POP() | BGFX_STATE_DEPTH_TEST_MASK \ ) -#define BGFX_D3D11_PROFILER_BEGIN(_view, _abgr) \ - BX_MACRO_BLOCK_BEGIN \ - if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) ) \ - { \ - wchar_t viewNameW[BGFX_CONFIG_MAX_VIEW_NAME]; \ - PIX_BEGINEVENT(_abgr, toViewNameW(viewNameW, _view) ); \ - } \ - BGFX_PROFILER_BEGIN(g_viewName[_view], _abgr); \ +#define BGFX_D3D11_PROFILER_BEGIN(_view, _abgr) \ + BX_MACRO_BLOCK_BEGIN \ + if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) ) \ + { \ + wchar_t viewNameW[BGFX_CONFIG_MAX_VIEW_NAME]; \ + PIX_BEGINEVENT(_abgr, toViewNameW(viewNameW, viewName) ); \ + } \ + BGFX_PROFILER_BEGIN(viewName, _abgr); \ BX_MACRO_BLOCK_END #define BGFX_D3D11_PROFILER_BEGIN_LITERAL(_name, _abgr) \ @@ -521,7 +521,7 @@ namespace bgfx { namespace d3d11 uint32_t m_frameNum; }; - Result m_result[BGFX_CONFIG_MAX_VIEWS+1]; + TimerResultT m_result; Query m_query[kMaxTimerQueries]; bx::RingBufferControl m_control; diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index ddeadce1c..fce51b921 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -8507,11 +8507,7 @@ namespace bgfx { namespace d3d12 { create(); - for (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii) - { - Result& result = m_result[ii]; - result.reset(); - } + m_result.reset(); } void TimerQueryD3D12::create() @@ -8573,10 +8569,7 @@ namespace bgfx { namespace d3d12 bgfx::resize(m_control, _size); create(); - for (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii) - { - m_result[ii].m_pending = 0; - } + m_result.resetPending(); } uint32_t TimerQueryD3D12::begin(uint32_t _resultIdx, uint32_t _frameNum) @@ -9511,6 +9504,8 @@ namespace bgfx { namespace d3d12 m_lastPso = NULL; SortKey key; uint16_t view = UINT16_MAX; + const View* renderView = &_render->view(0); + char viewName[BGFX_CONFIG_MAX_VIEW_NAME] = ""; FrameBufferHandle fbh = { BGFX_CONFIG_MAX_FRAME_BUFFERS }; UniformCacheState ucs(_render); @@ -9610,7 +9605,7 @@ namespace bgfx { namespace d3d12 m_batch.begin(); - viewState.m_rect = _render->m_view[0].m_rect; + viewState.m_rect = _render->view(0).m_rect; int32_t numItems = _render->m_numRenderItems; for (int32_t item = 0; item < numItems;) @@ -9638,6 +9633,8 @@ namespace bgfx { namespace d3d12 commandListChanged = true; view = key.m_view; + renderView = &_render->view(view); + viewState.setView(*renderView); currentPso = NULL; currentSamplerStateIdx = kInvalidHandle; currentProgram = BGFX_INVALID_HANDLE; @@ -9649,18 +9646,16 @@ namespace bgfx { namespace d3d12 } BGFX_D3D12_PROFILER_END(); - setViewType(view, " "); + formatViewName(viewName, _render, view, " "); BGFX_D3D12_PROFILER_BEGIN(view, kColorView); profiler.begin(view); - const View& renderView = _render->m_view[view]; - - resolveFrameBuffer(renderView.m_fbh); + resolveFrameBuffer(renderView->m_fbh); submitUniformCache(ucs, view); submitBlit(bs, view); - fbh = _render->m_view[view].m_fbh; + fbh = renderView->m_fbh; setFrameBuffer(fbh); stateMask = isValid(fbh) @@ -9668,10 +9663,10 @@ namespace bgfx { namespace d3d12 : UINT64_MAX ; - viewState.m_rect = renderView.m_rect; - const Rect& rect = renderView.m_rect; - const Rect& clippedRect = renderView.m_clippedRect; - const Rect& scissorRect = renderView.m_scissor; + viewState.m_rect = renderView->m_rect; + const Rect& rect = renderView->m_rect; + const Rect& clippedRect = renderView->m_clippedRect; + const Rect& scissorRect = renderView->m_scissor; viewHasScissor = !scissorRect.isZero(); viewScissorRect = viewHasScissor ? scissorRect : clippedRect; @@ -9680,8 +9675,8 @@ namespace bgfx { namespace d3d12 vp.TopLeftY = rect.m_y; vp.Width = rect.m_width; vp.Height = rect.m_height; - vp.MinDepth = renderView.m_minDepth; - vp.MaxDepth = renderView.m_maxDepth; + vp.MinDepth = renderView->m_minDepth; + vp.MaxDepth = renderView->m_maxDepth; m_commandList->RSSetViewports(1, &vp); D3D12_RECT rc; @@ -9692,7 +9687,7 @@ namespace bgfx { namespace d3d12 m_commandList->RSSetScissorRects(1, &rc); restoreScissor = false; - const Clear& clr = renderView.m_clear; + const Clear& clr = renderView->m_clear; if (BGFX_CLEAR_NONE != clr.m_flags) { @@ -9706,8 +9701,8 @@ namespace bgfx { namespace d3d12 if (m_variableRateShadingSupport) { const uint8_t shadingRate = m_additionalShadingRatesSupport - ? renderView.m_shadingRate - : bx::min(renderView.m_shadingRate, ShadingRate::Rate2x2) + ? renderView->m_shadingRate + : bx::min(renderView->m_shadingRate, ShadingRate::Rate2x2) ; reinterpret_cast(m_commandList)->RSSetShadingRate(s_shadingRate[shadingRate], NULL); } @@ -9719,7 +9714,7 @@ namespace bgfx { namespace d3d12 { wasCompute = true; - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_D3D12_PROFILER_END(); BGFX_D3D12_PROFILER_BEGIN(view, kColorCompute); @@ -9963,7 +9958,7 @@ namespace bgfx { namespace d3d12 || hasPredefined) { ProgramD3D12& program = m_program[currentProgram.idx]; - viewState.setPredefined<4>(this, view, program, _render, compute); + viewState.setPredefined<4>(this, view, *renderView, program, _render, compute); commitShaderConstants(key.m_program, gpuAddress); m_commandList->SetComputeRootConstantBufferView(ComputeRp::CBV, gpuAddress); } @@ -10016,7 +10011,7 @@ namespace bgfx { namespace d3d12 { wasCompute = false; - setViewType(view, " "); + setViewType(viewName, " "); BGFX_D3D12_PROFILER_END(); BGFX_D3D12_PROFILER_BEGIN(view, kColorDraw); @@ -10051,7 +10046,7 @@ namespace bgfx { namespace d3d12 if (0 != draw.m_streamMask) { const uint64_t newFlags = draw.m_stateFlags & stateMask; - const uint32_t sampleMask = _render->m_view[view].m_sampleMask & draw.m_sampleMask; + const uint32_t sampleMask = renderView->m_sampleMask & draw.m_sampleMask; uint64_t changedFlags = currentState.m_stateFlags ^ newFlags; currentState.m_stateFlags = newFlags; @@ -10146,7 +10141,7 @@ namespace bgfx { namespace d3d12 const DepthControl& depthControl = (UINT16_MAX != draw.m_depthBias) ? _render->m_frameCache.m_depthBiasCache.m_cache[draw.m_depthBias] - : _render->m_view[view].m_depthBias + : renderView->m_depthBias ; const bool depthClamp = depthControl.m_depthClamp; @@ -10433,7 +10428,7 @@ namespace bgfx { namespace d3d12 ProgramD3D12& program = m_program[currentProgram.idx]; uint32_t ref = (newFlags&BGFX_STATE_ALPHA_REF_MASK)>>BGFX_STATE_ALPHA_REF_SHIFT; viewState.m_alphaRef = ref/255.0f; - viewState.setPredefined<4>(this, view, program, _render, draw); + viewState.setPredefined<4>(this, view, *renderView, program, _render, draw); commitShaderConstants(key.m_program, gpuAddress); } @@ -10460,7 +10455,7 @@ namespace bgfx { namespace d3d12 if (wasCompute) { - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_D3D12_PROFILER_END(); BGFX_D3D12_PROFILER_BEGIN(view, kColorCompute); } diff --git a/src/renderer_d3d12.h b/src/renderer_d3d12.h index 6b652f148..68adef8a1 100644 --- a/src/renderer_d3d12.h +++ b/src/renderer_d3d12.h @@ -57,10 +57,10 @@ extern "C" uint64_t WINAPI bgfx_PIXEventsReplaceBlock(PIXEven # define PIX3_ENDEVENT(_commandList) BX_UNUSED(_commandList) #endif // BGFX_CONFIG_DEBUG_ANNOTATION -#define BGFX_D3D12_PROFILER_BEGIN(_view, _abgr) \ - BX_MACRO_BLOCK_BEGIN \ - PIX3_BEGINEVENT(m_commandList, _abgr, g_viewName[_view]); \ - BGFX_PROFILER_BEGIN(g_viewName[view], _abgr); \ +#define BGFX_D3D12_PROFILER_BEGIN(_view, _abgr) \ + BX_MACRO_BLOCK_BEGIN \ + PIX3_BEGINEVENT(m_commandList, _abgr, viewName); \ + BGFX_PROFILER_BEGIN(viewName, _abgr); \ BX_MACRO_BLOCK_END #define BGFX_D3D12_PROFILER_BEGIN_LITERAL(_name, _abgr) \ @@ -788,7 +788,7 @@ namespace bgfx { namespace d3d12 uint64_t m_frequency; - Result m_result[BGFX_CONFIG_MAX_VIEWS+1]; + TimerResultT m_result; Query m_query[kMaxTimerQueries]; ID3D12Resource* m_readback; diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 74e5a6195..897e41446 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -8770,6 +8770,8 @@ namespace bgfx { namespace gl ProgramHandle boundProgram = BGFX_INVALID_HANDLE; SortKey key; uint16_t view = UINT16_MAX; + const View* renderView = &_render->view(0); + char viewName[BGFX_CONFIG_MAX_VIEW_NAME] = ""; FrameBufferHandle fbh = { BGFX_CONFIG_MAX_FRAME_BUFFERS }; bool currentDepthClamp = false; // GL default: depth clipping on (WebGPU unclippedDepth = false). int32_t currentPolygonOffsetConstant = 0; @@ -8840,7 +8842,7 @@ namespace bgfx { namespace gl { GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) ); - viewState.m_rect = _render->m_view[0].m_rect; + viewState.m_rect = _render->view(0).m_rect; int32_t numItems = _render->m_numRenderItems; for (int32_t item = 0; item < numItems;) @@ -8862,6 +8864,8 @@ namespace bgfx { namespace gl if (viewChanged) { view = key.m_view; + renderView = &_render->view(view); + viewState.setView(*renderView); currentProgram = BGFX_INVALID_HANDLE; if (item > 1) @@ -8871,13 +8875,13 @@ namespace bgfx { namespace gl BGFX_GL_PROFILER_END(); - resolveFrameBuffer(_render->m_view[view].m_fbh); + resolveFrameBuffer(renderView->m_fbh); submitUniformCache(ucs, view); submitBlit(bs, view); - if (_render->m_view[view].m_fbh.idx != fbh.idx) + if (renderView->m_fbh.idx != fbh.idx) { - fbh = _render->m_view[view].m_fbh; + fbh = renderView->m_fbh; resolutionHeight = _render->m_mainSwapChain.height; resolutionHeight = setFrameBuffer(fbh, resolutionHeight, discardFlags); @@ -8892,12 +8896,12 @@ namespace bgfx { namespace gl ; } - setViewType(view, " "); + formatViewName(viewName, _render, view, " "); BGFX_GL_PROFILER_BEGIN(view, kColorView); profiler.begin(view); - viewState.m_rect = _render->m_view[view].m_rect; + viewState.m_rect = renderView->m_rect; const bool offscreenFb = isValid(fbh) && NULL == m_frameBuffers[fbh.idx].m_swapChain @@ -8912,9 +8916,9 @@ namespace bgfx { namespace gl ; ndcFlipRectY = !(offscreenFb && BX_ENABLED(BGFX_CONFIG_GL_NORMALIZE_NDC_CONVENTIONS) ); - const Rect& clippedRect = _render->m_view[view].m_clippedRect; + const Rect& clippedRect = renderView->m_clippedRect; - const Rect& scissorRect = _render->m_view[view].m_scissor; + const Rect& scissorRect = renderView->m_scissor; viewHasScissor = !scissorRect.isZero(); viewScissorRect = viewHasScissor ? scissorRect : clippedRect; @@ -8926,7 +8930,7 @@ namespace bgfx { namespace gl , viewState.m_rect.m_height ) ); - Clear& clear = _render->m_view[view].m_clear; + const Clear& clear = renderView->m_clear; discardFlags = clear.m_flags & BGFX_CLEAR_DISCARD_MASK; if (BGFX_CLEAR_NONE != (clear.m_flags & BGFX_CLEAR_MASK) ) @@ -8947,7 +8951,7 @@ namespace bgfx { namespace gl { wasCompute = true; - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_GL_PROFILER_END(); BGFX_GL_PROFILER_BEGIN(view, kColorCompute); } @@ -9056,7 +9060,7 @@ namespace bgfx { namespace gl commit(*program.m_constantBuffer); } - viewState.setPredefined<1>(this, view, program, _render, compute); + viewState.setPredefined<1>(this, view, *renderView, program, _render, compute); if (isValid(compute.m_indirectBuffer) ) { @@ -9104,7 +9108,7 @@ namespace bgfx { namespace gl { wasCompute = false; - setViewType(view, " "); + setViewType(viewName, " "); BGFX_GL_PROFILER_END(); BGFX_GL_PROFILER_BEGIN(view, kColorDraw); } @@ -9134,7 +9138,7 @@ namespace bgfx { namespace gl } const uint64_t newFlags = (draw.m_stateFlags & stateMask) ^ ndcFrontCcw; - const uint32_t sampleMask = _render->m_view[view].m_sampleMask & draw.m_sampleMask; + const uint32_t sampleMask = renderView->m_sampleMask & draw.m_sampleMask; uint64_t changedFlags = currentState.m_stateFlags ^ newFlags; currentState.m_stateFlags = newFlags; @@ -9241,7 +9245,7 @@ namespace bgfx { namespace gl { const bool depthClamp = (UINT16_MAX != draw.m_depthBias) ? _render->m_frameCache.m_depthBiasCache.m_cache[draw.m_depthBias].m_depthClamp - : _render->m_view[view].m_depthBias.m_depthClamp + : renderView->m_depthBias.m_depthClamp ; if (currentDepthClamp != depthClamp) { @@ -9260,7 +9264,7 @@ namespace bgfx { namespace gl { const DepthControl& depthControl = (UINT16_MAX != draw.m_depthBias) ? _render->m_frameCache.m_depthBiasCache.m_cache[draw.m_depthBias] - : _render->m_view[view].m_depthBias + : renderView->m_depthBias ; if (currentPolygonOffsetConstant != depthControl.m_constant @@ -9589,7 +9593,7 @@ namespace bgfx { namespace gl commit(*program.m_constantBuffer); } - viewState.setPredefined<1>(this, view, program, _render, draw); + viewState.setPredefined<1>(this, view, *renderView, program, _render, draw); { GLbitfield barrier = 0; @@ -9981,7 +9985,7 @@ namespace bgfx { namespace gl if (wasCompute) { - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_GL_PROFILER_END(); BGFX_GL_PROFILER_BEGIN(view, kColorCompute); } diff --git a/src/renderer_gl.h b/src/renderer_gl.h index c33301803..9ae2aed47 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -34,10 +34,10 @@ // on the following platforms. #define BGFX_GL_CONFIG_UNIFORM_CACHE BX_PLATFORM_EMSCRIPTEN -#define BGFX_GL_PROFILER_BEGIN(_view, _abgr) \ - BX_MACRO_BLOCK_BEGIN \ - GL_CHECK(glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, g_viewName[view]) ); \ - BGFX_PROFILER_BEGIN(g_viewName[view], _abgr); \ +#define BGFX_GL_PROFILER_BEGIN(_view, _abgr) \ + BX_MACRO_BLOCK_BEGIN \ + GL_CHECK(glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, viewName) ); \ + BGFX_PROFILER_BEGIN(viewName, _abgr); \ BX_MACRO_BLOCK_END #define BGFX_GL_PROFILER_BEGIN_LITERAL(_name, _abgr) \ @@ -1667,11 +1667,7 @@ namespace bgfx { namespace gl { create(0, m_control.getSize() ); - for (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii) - { - Result& result = m_result[ii]; - result.reset(); - } + m_result.reset(); } void destroy() @@ -1845,7 +1841,7 @@ namespace bgfx { namespace gl bool m_ready; }; - Result m_result[BGFX_CONFIG_MAX_VIEWS+1]; + TimerResultT m_result; Query m_query[kMaxTimerQueries]; bx::RingBufferControl m_control; diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp index aae2f2bfd..0808cd31b 100644 --- a/src/renderer_mtl.cpp +++ b/src/renderer_mtl.cpp @@ -5513,10 +5513,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_frequency = kNanosecondsPerSecond; m_frameNum = 0; - for (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii) - { - m_result[ii].reset(); - } + m_result.reset(); for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameResult); ++ii) { @@ -6131,6 +6128,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames ProgramHandle currentProgram = BGFX_INVALID_HANDLE; SortKey key; uint16_t view = UINT16_MAX; + const View* renderView = &_render->view(0); + char viewName[BGFX_CONFIG_MAX_VIEW_NAME] = ""; FrameBufferHandle fbh = { BGFX_CONFIG_MAX_FRAME_BUFFERS }; UniformCacheState ucs(_render); @@ -6176,7 +6175,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (0 == (_render->m_debug&BGFX_DEBUG_IFH) ) { - viewState.m_rect = _render->m_view[0].m_rect; + viewState.m_rect = _render->view(0).m_rect; int32_t numItems = _render->m_numRenderItems; for (int32_t item = 0; item < numItems;) @@ -6199,6 +6198,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames || (!isCompute && wasCompute) ) { view = key.m_view; + renderView = &_render->view(view); + viewState.setView(*renderView); currentProgram = BGFX_INVALID_HANDLE; if (item > 1) @@ -6207,17 +6208,17 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames } BGFX_MTL_PROFILER_END(); - setViewType(view, " "); + formatViewName(viewName, _render, view, " "); BGFX_MTL_PROFILER_BEGIN(view, kColorView); profiler.begin(view); - viewState.m_rect = _render->m_view[view].m_rect; + viewState.m_rect = renderView->m_rect; submitUniformCache(ucs, view); if (isValid(m_fbh) - && m_fbh.idx != _render->m_view[view].m_fbh.idx) + && m_fbh.idx != renderView->m_fbh.idx) { resolveFrameBuffer(); } @@ -6226,7 +6227,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (!isCompute) { - const FrameBufferHandle viewFbh = _render->m_view[view].m_fbh; + const FrameBufferHandle viewFbh = renderView->m_fbh; uint32_t width = m_mainSwapChain.width; uint32_t height = m_mainSwapChain.height; @@ -6246,20 +6247,20 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames ); Rect clippedRect; - clippedRect.setIntersect(_render->m_view[view].m_clippedRect, framebufferRect); + clippedRect.setIntersect(renderView->m_clippedRect, framebufferRect); Rect scissorRect; - scissorRect.setIntersect(_render->m_view[view].m_scissor, framebufferRect); + scissorRect.setIntersect(renderView->m_scissor, framebufferRect); - viewHasScissor = !_render->m_view[view].m_scissor.isZero(); + viewHasScissor = !renderView->m_scissor.isZero(); viewScissorRect = viewHasScissor ? scissorRect : clippedRect; - Clear& clr = _render->m_view[view].m_clear; + const Clear& clr = renderView->m_clear; const Rect viewRect = viewState.m_rect; bool clearWithRenderPass = false; if (NULL == m_renderCommandEncoder - || fbh.idx != _render->m_view[view].m_fbh.idx + || fbh.idx != renderView->m_fbh.idx || profileViews) { endEncoding(); @@ -6269,7 +6270,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_gpuTimer.attach(renderPassDescriptor); - fbh = _render->m_view[view].m_fbh; + fbh = renderView->m_fbh; const bool hasDepthAttachment = true && isValid(fbh) @@ -6410,7 +6411,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (m_variableRateShadingSupported) { - MTL::RasterizationRateLayerDescriptor* rrld = newRasterizationRateLayerDescriptor(s_shadingRate[_render->m_view[view].m_shadingRate]); + MTL::RasterizationRateLayerDescriptor* rrld = newRasterizationRateLayerDescriptor(s_shadingRate[renderView->m_shadingRate]); MTL::RasterizationRateMapDescriptor* rrmd = newRasterizationRateMapDescriptor(); rrmd->setScreenSize(MTL::Size::Make(viewRect.m_width, viewRect.m_height, 0) ); rrmd->setLayer(rrld, 0); @@ -6431,7 +6432,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) ) { - rce->pushDebugGroup(nsstr(g_viewName[view]) ); + rce->pushDebugGroup(nsstr(viewName) ); } rce->setTriangleFillMode( (MTL::TriangleFillMode)wireframe ? MTL::TriangleFillModeLines : MTL::TriangleFillModeFill); @@ -6472,7 +6473,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames endEncoding(); rce = NULL; - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_MTL_PROFILER_END(); BGFX_MTL_PROFILER_BEGIN(view, kColorCompute); @@ -6486,9 +6487,9 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (viewChanged && BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) ) { - g_viewName[view][3] = L'C'; - m_computeCommandEncoder->pushDebugGroup(nsstr(g_viewName[view]) ); - g_viewName[view][3] = L' '; + viewName[4] = 'C'; + m_computeCommandEncoder->pushDebugGroup(nsstr(viewName) ); + viewName[4] = ' '; } const RenderCompute& compute = renderItem.compute; @@ -6521,7 +6522,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames commit(*vcb); } - viewState.setPredefined<4>(this, view, *currentPso, _render, compute); + viewState.setPredefined<4>(this, view, *renderView, *currentPso, _render, compute); if (0 != vertexUniformBufferSize) { @@ -6626,7 +6627,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames wasCompute = false; currentProgram = BGFX_INVALID_HANDLE; - setViewType(view, " "); + setViewType(viewName, " "); BGFX_MTL_PROFILER_END(); BGFX_MTL_PROFILER_BEGIN(view, kColorDraw); } @@ -6726,7 +6727,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames { const DepthControl& depthControl = (UINT16_MAX != draw.m_depthBias) ? _render->m_frameCache.m_depthBiasCache.m_cache[draw.m_depthBias] - : _render->m_view[view].m_depthBias + : renderView->m_depthBias ; if (m_supportsDepthClipMode) @@ -6791,7 +6792,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames bool vertexStreamChanged = hasVertexStreamChanged(currentState, draw); - const uint32_t sampleMask = _render->m_view[view].m_sampleMask & draw.m_sampleMask; + const uint32_t sampleMask = renderView->m_sampleMask & draw.m_sampleMask; if (key.m_program.idx != currentProgram.idx || vertexStreamChanged @@ -6911,7 +6912,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames commit(*fcb); } - viewState.setPredefined<4>(this, view, *currentPso, _render, draw); + viewState.setPredefined<4>(this, view, *renderView, *currentPso, _render, draw); if (0 != vertexUniformBufferSize || 0 != fragmentUniformBufferSize) @@ -7148,7 +7149,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames { invalidateCompute(); - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_MTL_PROFILER_END(); BGFX_MTL_PROFILER_BEGIN(view, kColorCompute); } diff --git a/src/renderer_mtl.h b/src/renderer_mtl.h index 390c15f10..2eea40fd4 100644 --- a/src/renderer_mtl.h +++ b/src/renderer_mtl.h @@ -15,9 +15,9 @@ #include "renderer.h" -#define BGFX_MTL_PROFILER_BEGIN(_view, _abgr) \ - BX_MACRO_BLOCK_BEGIN \ - BGFX_PROFILER_BEGIN(g_viewName[view], _abgr); \ +#define BGFX_MTL_PROFILER_BEGIN(_view, _abgr) \ + BX_MACRO_BLOCK_BEGIN \ + BGFX_PROFILER_BEGIN(viewName, _abgr); \ BX_MACRO_BLOCK_END #define BGFX_MTL_PROFILER_BEGIN_LITERAL(_name, _abgr) \ @@ -694,7 +694,7 @@ namespace bgfx { namespace mtl uint64_t m_frequency; uint32_t m_frameNum; - Result m_result[BGFX_CONFIG_MAX_VIEWS+1]; + TimerResultT m_result; Result m_frameResult[4]; bx::RingBufferControl m_control; diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 0828ad4fe..fa39ed4dd 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -6355,10 +6355,7 @@ VK_DESTROY { BGFX_PROFILER_SCOPE("TimerQueryVK::init", kColorFrame); - for (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii) - { - m_result[ii].reset(); - } + m_result.reset(); return create(); } @@ -6436,10 +6433,7 @@ VK_DESTROY bgfx::resize(m_control, _size); VK_CHECK(create() ); - for (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii) - { - m_result[ii].m_pending = 0; - } + m_result.resetPending(); } uint32_t TimerQueryVK::begin(uint32_t _resultIdx, uint32_t _frameNum) @@ -10449,6 +10443,8 @@ VK_DESTROY VkIndexType currentIndexFormat = VK_INDEX_TYPE_MAX_ENUM; SortKey key; uint16_t view = UINT16_MAX; + const View* renderView = &_render->view(0); + char viewName[BGFX_CONFIG_MAX_VIEW_NAME] = ""; FrameBufferHandle fbh = { BGFX_CONFIG_MAX_FRAME_BUFFERS }; UniformCacheState ucs(_render); @@ -10516,7 +10512,7 @@ VK_DESTROY if (0 == (_render->m_debug&BGFX_DEBUG_IFH) ) { - viewState.m_rect = _render->m_view[0].m_rect; + viewState.m_rect = _render->view(0).m_rect; int32_t numItems = _render->m_numRenderItems; for (int32_t item = 0; item < numItems;) @@ -10539,10 +10535,12 @@ VK_DESTROY if (viewChanged) { view = key.m_view; + renderView = &_render->view(view); + viewState.setView(*renderView); currentProgram = BGFX_INVALID_HANDLE; hasPredefined = false; - if (_render->m_view[view].m_fbh.idx != fbh.idx) + if (renderView->m_fbh.idx != fbh.idx) { if ( beginRenderPass ) { @@ -10550,7 +10548,7 @@ VK_DESTROY beginRenderPass = false; } - fbh = _render->m_view[view].m_fbh; + fbh = renderView->m_fbh; setFrameBuffer(fbh); stateMask = isValid(fbh) @@ -10575,8 +10573,8 @@ VK_DESTROY } if (beginRenderPass && (false - || _render->m_view[view].m_fbh.idx != fbh.idx - || !_render->m_view[view].m_rect.isEqual(viewState.m_rect) + || renderView->m_fbh.idx != fbh.idx + || !renderView->m_rect.isEqual(viewState.m_rect) || profiler.m_enabled ) ) { @@ -10599,7 +10597,7 @@ VK_DESTROY submitBlit(bs, view); BGFX_VK_PROFILER_END(); - setViewType(view, " "); + formatViewName(viewName, _render, view, " "); BGFX_VK_PROFILER_BEGIN(view, kColorView); profiler.begin(view); @@ -10610,7 +10608,7 @@ VK_DESTROY if (isFrameBufferValid) { - const Clear& clr = _render->m_view[view].m_clear; + const Clear& clr = renderView->m_clear; const bool partialColorClear = true && 0 != (clr.m_flags & BGFX_CLEAR_COLOR) @@ -10622,8 +10620,8 @@ VK_DESTROY : clr.m_flags ); - viewState.m_rect = _render->m_view[view].m_rect; - const Rect& rect = _render->m_view[view].m_rect; + viewState.m_rect = renderView->m_rect; + const Rect& rect = renderView->m_rect; const Rect framebufferRect( 0 @@ -10633,9 +10631,9 @@ VK_DESTROY ); Rect renderArea; - renderArea.setIntersect(_render->m_view[view].m_clippedRect, framebufferRect); + renderArea.setIntersect(renderView->m_clippedRect, framebufferRect); - Rect scissorRect = _render->m_view[view].m_scissor; + Rect scissorRect = renderView->m_scissor; viewHasScissor = !scissorRect.isZero(); viewScissorRect = viewHasScissor ? scissorRect : renderArea; restoreScissor = false; @@ -10652,8 +10650,8 @@ VK_DESTROY vp.y = float(rect.m_y + rect.m_height); vp.width = float(rect.m_width); vp.height = -float(rect.m_height); - vp.minDepth = _render->m_view[view].m_minDepth; - vp.maxDepth = _render->m_view[view].m_maxDepth; + vp.minDepth = renderView->m_minDepth; + vp.maxDepth = renderView->m_maxDepth; vkCmdSetViewport(m_commandBuffer, 0, 1, &vp); VkRect2D rc; @@ -10783,7 +10781,7 @@ VK_DESTROY vkCmdSetFragmentShadingRateKHR( m_commandBuffer - , &s_shadingRate[_render->m_view[view].m_shadingRate].fragmentSize + , &s_shadingRate[renderView->m_shadingRate].fragmentSize , combinerOp ); } @@ -10798,7 +10796,7 @@ VK_DESTROY currentBindHash = 0; BGFX_VK_PROFILER_END(); - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_VK_PROFILER_BEGIN(view, kColorCompute); if (beginRenderPass) @@ -10858,7 +10856,7 @@ VK_DESTROY if (constantsChanged || hasPredefined) { - viewState.setPredefined<4>(this, view, program, _render, compute); + viewState.setPredefined<4>(this, view, *renderView, program, _render, compute); } if (VK_NULL_HANDLE != program.m_descriptorSetLayout) @@ -10976,7 +10974,7 @@ VK_DESTROY } const uint64_t state = draw.m_stateFlags & stateMask; - const uint32_t sampleMask = _render->m_view[view].m_sampleMask & draw.m_sampleMask; + const uint32_t sampleMask = renderView->m_sampleMask & draw.m_sampleMask; const uint64_t stencil = draw.m_stencil & stencilMask; const uint64_t changedFlags = currentState.m_stateFlags ^ state; currentState.m_stateFlags = state; @@ -11056,7 +11054,7 @@ VK_DESTROY const DepthControl& depthControl = (UINT16_MAX != draw.m_depthBias) ? _render->m_frameCache.m_depthBiasCache.m_cache[draw.m_depthBias] - : _render->m_view[view].m_depthBias + : renderView->m_depthBias ; if (pipelineState.valid @@ -11218,7 +11216,7 @@ VK_DESTROY { uint32_t ref = (draw.m_stateFlags & BGFX_STATE_ALPHA_REF_MASK) >> BGFX_STATE_ALPHA_REF_SHIFT; viewState.m_alphaRef = ref / 255.0f; - viewState.setPredefined<4>(this, view, program, _render, draw); + viewState.setPredefined<4>(this, view, *renderView, program, _render, draw); } if (VK_NULL_HANDLE != program.m_descriptorSetLayout) @@ -11451,7 +11449,7 @@ VK_DESTROY if (wasCompute) { - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_VK_PROFILER_END(); BGFX_VK_PROFILER_BEGIN(view, kColorCompute); } diff --git a/src/renderer_vk.h b/src/renderer_vk.h index dee108cb3..a817bcc73 100644 --- a/src/renderer_vk.h +++ b/src/renderer_vk.h @@ -303,10 +303,10 @@ # define BGFX_VK_END_DEBUG_UTILS_LABEL() BX_NOOP() #endif // BGFX_CONFIG_DEBUG_ANNOTATION -#define BGFX_VK_PROFILER_BEGIN(_view, _abgr) \ - BX_MACRO_BLOCK_BEGIN \ - BGFX_VK_BEGIN_DEBUG_UTILS_LABEL(g_viewName[view], _abgr); \ - BGFX_PROFILER_BEGIN(g_viewName[view], _abgr); \ +#define BGFX_VK_PROFILER_BEGIN(_view, _abgr) \ + BX_MACRO_BLOCK_BEGIN \ + BGFX_VK_BEGIN_DEBUG_UTILS_LABEL(viewName, _abgr); \ + BGFX_PROFILER_BEGIN(viewName, _abgr); \ BX_MACRO_BLOCK_END #define BGFX_VK_PROFILER_BEGIN_LITERAL(_name, _abgr) \ @@ -643,7 +643,7 @@ VK_DESTROY_FUNC(DescriptorSet); uint64_t m_frequency; - Result m_result[BGFX_CONFIG_MAX_VIEWS+1]; + TimerResultT m_result; Query m_query[kMaxTimerQueries]; VkBuffer m_readback; diff --git a/src/renderer_webgpu.cpp b/src/renderer_webgpu.cpp index e1e2987ce..1931f03ab 100644 --- a/src/renderer_webgpu.cpp +++ b/src/renderer_webgpu.cpp @@ -6005,10 +6005,7 @@ WGPU_IMPORT void TimerQueryWGPU::init() { - for (uint32_t ii = 0; ii < BX_COUNTOF(m_result); ++ii) - { - m_result[ii].reset(); - } + m_result.reset(); m_supported = isFeatureSupported(WGPUFeatureName_TimestampQuery); @@ -6017,6 +6014,20 @@ WGPU_IMPORT return; } + create(kMinTimerQueries); + } + + void TimerQueryWGPU::shutdown() + { + destroy(); + } + + void TimerQueryWGPU::create(uint32_t _num) + { + m_numQueries = bx::min(_num, kMaxQueries); + m_query = (Query*)bx::alloc(g_allocator, sizeof(Query)*m_numQueries); + bgfx::resize(m_control, m_numQueries); + WGPUDevice device = s_renderWGPU->m_device; WGPUQuerySetDescriptor querySetDesc = @@ -6024,7 +6035,7 @@ WGPU_IMPORT .nextInChain = NULL, .label = toWGPUStringView("TimerQuery"), .type = WGPUQueryType_Timestamp, - .count = kNumTimestamps, + .count = m_numQueries*2, }; m_querySet = WGPU_CHECK(wgpuDeviceCreateQuerySet(device, &querySetDesc) ); @@ -6037,7 +6048,7 @@ WGPU_IMPORT | WGPUBufferUsage_CopySrc | WGPUBufferUsage_QueryResolve , - .size = kBufferSize, + .size = getBufferSize(), .mappedAtCreation = false, }; @@ -6051,18 +6062,38 @@ WGPU_IMPORT | WGPUBufferUsage_MapRead | WGPUBufferUsage_CopyDst , - .size = kBufferSize, + .size = getBufferSize(), .mappedAtCreation = false, }; m_readback = WGPU_CHECK(wgpuDeviceCreateBuffer(device, &readbackBufferDesc) ); } - void TimerQueryWGPU::shutdown() + void TimerQueryWGPU::destroy() { wgpuDestroy(m_querySet); wgpuDestroy(m_resolve); wgpuDestroy(m_readback); + + bx::free(g_allocator, m_query); + m_query = NULL; + m_numQueries = 0; + } + + void TimerQueryWGPU::resize(uint32_t _num) + { + if (!m_supported + || m_mapPending + || m_resolved + || bx::min(_num, kMaxQueries) == m_numQueries) + { + return; + } + + destroy(); + create(_num); + + m_result.resetPending(); } void TimerQueryWGPU::writeTimestamp(uint32_t _index) @@ -6137,7 +6168,7 @@ WGPU_IMPORT commandEncoder , m_querySet , 0 - , kNumTimestamps + , m_numQueries*2 , m_resolve , 0 ) ); @@ -6148,7 +6179,7 @@ WGPU_IMPORT , 0 , m_readback , 0 - , kBufferSize + , getBufferSize() ) ); m_resolvedFrameNum = _frameNum; @@ -6177,7 +6208,7 @@ WGPU_IMPORT m_readback , WGPUMapMode_Read , 0 - , kBufferSize + , getBufferSize() , { .nextInChain = NULL, .mode = WGPUCallbackMode_AllowProcessEvents, @@ -6189,7 +6220,7 @@ WGPU_IMPORT void TimerQueryWGPU::consumeResults() { - const uint64_t* timestamp = (const uint64_t*)wgpuBufferGetConstMappedRange(m_readback, 0, kBufferSize); + const uint64_t* timestamp = (const uint64_t*)wgpuBufferGetConstMappedRange(m_readback, 0, getBufferSize() ); if (NULL != timestamp) { @@ -6813,6 +6844,7 @@ WGPU_IMPORT m_occlusionQuery.readResultsAsync(_render); m_gpuTimer.readResultsAsync(); WGPU_CHECK(wgpuInstanceProcessEvents(s_renderWGPU->m_instance) ); + m_gpuTimer.resize(getNumTimerQueries(_render, m_gpuTimer.m_control.getSize() ) ); if (updateResolution(_render->m_mainSwapChain, _render->m_reset) ) { @@ -6879,6 +6911,8 @@ WGPU_IMPORT bool hasPredefined = false; SortKey key; uint16_t view = UINT16_MAX; + const View* renderView = &_render->view(0); + char viewName[BGFX_CONFIG_MAX_VIEW_NAME] = ""; FrameBufferHandle fbh = BGFX_INVALID_HANDLE; UniformCacheState ucs(_render); @@ -6958,7 +6992,7 @@ WGPU_IMPORT if (0 == (_render->m_debug&BGFX_DEBUG_IFH) ) { - viewState.m_rect = _render->m_view[0].m_rect; + viewState.m_rect = _render->view(0).m_rect; int32_t numItems = _render->m_numRenderItems; for (int32_t item = 0; item < numItems;) @@ -6980,13 +7014,15 @@ WGPU_IMPORT if (viewChanged) { view = key.m_view; + renderView = &_render->view(view); + viewState.setView(*renderView); currentProgram = BGFX_INVALID_HANDLE; currentState.clear(); hasPredefined = false; pipelineState.valid = false; bindState.valid = false; - if (_render->m_view[view].m_fbh.idx != fbh.idx) + if (renderView->m_fbh.idx != fbh.idx) { if (NULL != renderPassEncoder) { @@ -7008,7 +7044,7 @@ WGPU_IMPORT oldFb.resolve(m_cmd.m_commandEncoder); } - fbh = _render->m_view[view].m_fbh; + fbh = renderView->m_fbh; stateMask = isValid(fbh) ? getAttachmentStateMask(m_frameBuffers[fbh.idx].m_attachment, m_frameBuffers[fbh.idx].m_numAttachments) @@ -7042,7 +7078,7 @@ WGPU_IMPORT submitBlit(bs, view); BGFX_WGPU_PROFILER_END(); - setViewType(view, " "); + formatViewName(viewName, _render, view, " "); BGFX_WGPU_PROFILER_BEGIN(view, kColorView); profiler.begin(view); @@ -7061,23 +7097,23 @@ WGPU_IMPORT : fb.m_depthStencilView ; - viewState.m_rect = _render->m_view[view].m_rect; + viewState.m_rect = renderView->m_rect; const Rect fbRect(0, 0, bx::narrowCast(fb.m_width), bx::narrowCast(fb.m_height) ); - const Rect& viewRect = _render->m_view[view].m_rect; + const Rect& viewRect = renderView->m_rect; Rect clippedRect; - clippedRect.setIntersect(_render->m_view[view].m_clippedRect, fbRect); + clippedRect.setIntersect(renderView->m_clippedRect, fbRect); - Rect scissorRect = _render->m_view[view].m_scissor; + Rect scissorRect = renderView->m_scissor; scissorRect.intersect(fbRect); viewHasScissor = !scissorRect.isZero(); viewScissorRect = viewHasScissor ? scissorRect : clippedRect; restoreScissor = false; - const Clear& clr = _render->m_view[view].m_clear; + const Clear& clr = renderView->m_clear; const bool needClear = BGFX_CLEAR_NONE != ( (BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH|BGFX_CLEAR_STENCIL) & clr.m_flags); const bool clearWhole = clippedRect.isEqual(fbRect); @@ -7189,7 +7225,7 @@ WGPU_IMPORT WGPURenderPassDescriptor renderPassDesc = { .nextInChain = NULL, - .label = toWGPUStringView(g_viewName[view]), + .label = toWGPUStringView(viewName), .colorAttachmentCount = numColorAttachments, .colorAttachments = colorAttachment, .depthStencilAttachment = NULL == depthStencilTextureView @@ -7246,7 +7282,7 @@ WGPU_IMPORT if (NULL == computePassEncoder) { BGFX_WGPU_PROFILER_END(); - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_WGPU_PROFILER_BEGIN(view, kColorCompute); if (NULL != renderPassEncoder) @@ -7296,7 +7332,7 @@ WGPU_IMPORT if (constantsChanged || hasPredefined) { - viewState.setPredefined<4>(this, view, program, _render, compute); + viewState.setPredefined<4>(this, view, *renderView, program, _render, compute); m_uniformScratchBuffer.write(sbo, m_vsScratch, vsSize); } @@ -7355,7 +7391,7 @@ WGPU_IMPORT WGPU_CHECK(wgpuComputePassEncoderEnd(computePassEncoder) ); wgpuRelease(computePassEncoder); - setViewType(view, " "); + setViewType(viewName, " "); BGFX_WGPU_PROFILER_END(); BGFX_WGPU_PROFILER_BEGIN(view, kColorDraw); } @@ -7389,7 +7425,7 @@ WGPU_IMPORT rendererUpdateUniforms(this, _render->m_uniformBuffer[draw.m_uniformIdx], draw.m_uniformBegin, draw.m_uniformEnd); const uint64_t state = draw.m_stateFlags & stateMask; - const uint32_t sampleMask = _render->m_view[view].m_sampleMask & draw.m_sampleMask; + const uint32_t sampleMask = renderView->m_sampleMask & draw.m_sampleMask; const uint8_t numInstanceData = uint8_t(draw.m_instanceDataStride/16); const bool drawIsIndex16 = draw.isIndex16(); @@ -7416,7 +7452,7 @@ WGPU_IMPORT { const DepthControl& depthControl = (UINT16_MAX != draw.m_depthBias) ? _render->m_frameCache.m_depthBiasCache.m_cache[draw.m_depthBias] - : _render->m_view[view].m_depthBias + : renderView->m_depthBias ; const bool depthClamp = depthControl.m_depthClamp; @@ -7497,7 +7533,7 @@ WGPU_IMPORT { const uint32_t ref = (draw.m_stateFlags&BGFX_STATE_ALPHA_REF_MASK)>>BGFX_STATE_ALPHA_REF_SHIFT; viewState.m_alphaRef = ref/255.0f; - viewState.setPredefined<4>(this, view, program, _render, draw); + viewState.setPredefined<4>(this, view, *renderView, program, _render, draw); } ChunkedScratchBufferOffset sbo; @@ -7874,7 +7910,7 @@ WGPU_IMPORT WGPU_CHECK(wgpuComputePassEncoderEnd(computePassEncoder) ); wgpuRelease(computePassEncoder); - setViewType(view, "C"); + setViewType(viewName, "C"); BGFX_WGPU_PROFILER_END(); BGFX_WGPU_PROFILER_BEGIN(view, kColorCompute); } diff --git a/src/renderer_webgpu.h b/src/renderer_webgpu.h index 5d9850c6f..f5cec910c 100644 --- a/src/renderer_webgpu.h +++ b/src/renderer_webgpu.h @@ -366,9 +366,9 @@ /*WGPU_DESTROY_FUNC(ResourceTable);*/ \ /* end */ -#define BGFX_WGPU_PROFILER_BEGIN(_view, _abgr) \ - BX_MACRO_BLOCK_BEGIN \ - BGFX_PROFILER_BEGIN(g_viewName[view], _abgr); \ +#define BGFX_WGPU_PROFILER_BEGIN(_view, _abgr) \ + BX_MACRO_BLOCK_BEGIN \ + BGFX_PROFILER_BEGIN(viewName, _abgr); \ BX_MACRO_BLOCK_END #define BGFX_WGPU_PROFILER_BEGIN_LITERAL(_name, _abgr) \ @@ -811,10 +811,12 @@ namespace wgpu { { TimerQueryWGPU() : m_frequency(UINT64_C(1000000000) ) + , m_query(NULL) + , m_numQueries(0) , m_querySet(NULL) , m_resolve(NULL) , m_readback(NULL) - , m_control(BX_COUNTOF(m_result) ) + , m_control(0) , m_resolvedFrameNum(0) , m_supported(false) , m_resolved(false) @@ -824,6 +826,9 @@ namespace wgpu { void init(); void shutdown(); + void create(uint32_t _num); + void destroy(); + void resize(uint32_t _num); uint32_t begin(uint32_t _resultIdx, uint32_t _frameNum); void end(uint32_t _idx); void resolve(uint32_t _frameNum); @@ -855,13 +860,18 @@ namespace wgpu { uint32_t m_frameNum; }; - static constexpr uint32_t kNumTimestamps = (BGFX_CONFIG_MAX_VIEWS+1)*2; - static constexpr uint64_t kBufferSize = kNumTimestamps * sizeof(uint64_t); + static constexpr uint32_t kMaxQueries = bx::min(kMaxTimerQueries, 4096/2); + + uint64_t getBufferSize() const + { + return uint64_t(m_numQueries)*2*sizeof(uint64_t); + } uint64_t m_frequency; - Result m_result[BGFX_CONFIG_MAX_VIEWS+1]; - Query m_query[BGFX_CONFIG_MAX_VIEWS+1]; + TimerResultT m_result; + Query* m_query; + uint32_t m_numQueries; WGPUQuerySet m_querySet; WGPUBuffer m_resolve;