diff --git a/bindings/bf/bgfx.bf b/bindings/bf/bgfx.bf index 978052b52..97b8c860c 100644 --- a/bindings/bf/bgfx.bf +++ b/bindings/bf/bgfx.bf @@ -959,6 +959,64 @@ public static class bgfx ReservedMask = 0x80000000, } + [AllowDuplicates] + public enum SwapChainFlags : uint32 + { + /// + /// Enable 2x MSAA. + /// + MsaaX2 = 0x00000010, + + /// + /// Enable 4x MSAA. + /// + MsaaX4 = 0x00000020, + + /// + /// Enable 8x MSAA. + /// + MsaaX8 = 0x00000030, + + /// + /// Enable 16x MSAA. + /// + MsaaX16 = 0x00000040, + MsaaShift = 4, + MsaaMask = 0x00000070, + + /// + /// No swap chain flags. + /// + None = 0x00000000, + + /// + /// Not supported yet. + /// + Fullscreen = 0x00000001, + + /// + /// Enable sRGB backbuffer. + /// + SrgbBackbuffer = 0x00008000, + + /// + /// Enable HDR10 rendering. + /// + Hdr10 = 0x00010000, + + /// + /// Enable HiDPI rendering. + /// + Hidpi = 0x00020000, + + /// + /// Transparent backbuffer. Availability depends on: `BGFX_CAPS_TRANSPARENT_BACKBUFFER`. + /// + TransparentBackbuffer = 0x00100000, + FullscreenShift = 0, + FullscreenMask = 0x00000001, + } + [AllowDuplicates] public enum CapsFlags : uint64 { @@ -1374,7 +1432,7 @@ public static class bgfx Intel = 0x8086, /// - /// nVidia adapter. + /// NVIDIA adapter. /// Nvidia = 0x10de, @@ -2315,32 +2373,32 @@ public static class bgfx public enum BackbufferRatio : uint32 { /// - /// Equal to backbuffer. + /// Equal to the main window's backbuffer. /// Equal, /// - /// One half size of backbuffer. + /// One half size of the main window's backbuffer. /// Half, /// - /// One quarter size of backbuffer. + /// One quarter size of the main window's backbuffer. /// Quarter, /// - /// One eighth size of backbuffer. + /// One eighth size of the main window's backbuffer. /// Eighth, /// - /// One sixteenth size of backbuffer. + /// One sixteenth size of the main window's backbuffer. /// Sixteenth, /// - /// Double size of backbuffer. + /// Double size of the main window's backbuffer. /// Double, @@ -2646,26 +2704,24 @@ public static class bgfx [CRepr] public struct PlatformData { - public void* ndt; - public void* nwh; public void* context; public void* queue; - public void* backBuffer; - public void* backBufferDS; public NativeWindowHandleType type; } [CRepr] - public struct Resolution + public struct SwapChain { - public TextureFormat formatColor; - public TextureFormat formatDepthStencil; + public void* nwh; + public void* ndt; public uint32 width; public uint32 height; - public uint32 reset; + public uint32 flags; + public TextureFormat formatColor; + public TextureFormat formatDepthStencil; + public TextureHandle depth; public uint8 numBackBuffers; public uint8 maxFrameLatency; - public uint8 debugTextScale; } [CRepr] @@ -2692,7 +2748,8 @@ public static class bgfx public uint8 fallback; public uint8 videoDecode; public PlatformData platformData; - public Resolution resolution; + public SwapChain swapChain; + public uint32 reset; public Limits limits; public void* callback; public void* allocator; @@ -3220,13 +3277,11 @@ public static class bgfx /// /// /// - /// Back-buffer width. - /// Back-buffer height. - /// See: `BGFX_RESET_*` for more info. - `BGFX_RESET_NONE` - No reset flags. - `BGFX_RESET_FULLSCREEN` - Not supported yet. - `BGFX_RESET_MSAA_X[2/4/8/16]` - Enable 2, 4, 8 or 16 x MSAA. - `BGFX_RESET_VSYNC` - Enable V-Sync. - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. - `BGFX_RESET_CAPTURE` - Begin screen capture. - `BGFX_RESET_FLUSH_AFTER_RENDER` - Flush rendering after submitting to GPU. - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip occurs. Default behaviour is that flip occurs before rendering new frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. - `BGFX_RESET_SRGB_BACKBUFFER` - Enable sRGB back-buffer. - /// Texture format. See: `TextureFormat::Enum`. + /// See: `BGFX_RESET_*` for more info. - `BGFX_RESET_NONE` - No reset flags. - `BGFX_RESET_VSYNC` - Enable V-Sync. - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. - `BGFX_RESET_CAPTURE` - Begin screen capture. - `BGFX_RESET_FLUSH_AFTER_RENDER` - Flush rendering after submitting to GPU. - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip occurs. Default behaviour is that flip occurs before rendering new frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. Per-surface settings are not here. `BGFX_SWAP_CHAIN_*` flags belong on `SwapChain::flags`, and are ignored if passed here. + /// Main window swap chain. When `NULL` the main window is left untouched and only the device and frame globals above are applied, which is what an application driving its own swap chains wants. Otherwise the main window takes on this description: resize it, change its format, or change its per-surface flags. Fields left neutral keep their current value, and `nwh`/`ndt` are ignored -- main's are bgfx's own. Must be `NULL` when `bgfx::init` created no main window. /// [LinkName("bgfx_reset")] - public static extern void reset(uint32 _width, uint32 _height, uint32 _flags, TextureFormat _format); + public static extern void reset(uint32 _flags, SwapChain* _swapChain); /// /// Advance to next frame. This is the main frame-advancement call on the @@ -3354,9 +3409,11 @@ public static class bgfx /// /// /// Available flags: - `BGFX_DEBUG_IFH` - Infinitely fast hardware. When this flag is set all rendering calls will be skipped. This is useful when profiling to quickly assess potential bottlenecks between CPU and GPU. - `BGFX_DEBUG_PROFILER` - Enable profiler. - `BGFX_DEBUG_STATS` - Display internal statistics. - `BGFX_DEBUG_TEXT` - Display debug text. - `BGFX_DEBUG_WIREFRAME` - Wireframe rendering. All rendering primitives will be rendered as lines. + /// Frame buffer the debug text and statistics are drawn on. Invalid handle selects the window bgfx was initialized with. + /// Debug text scale factor. 0 is the same as 1. /// [LinkName("bgfx_set_debug")] - public static extern void set_debug(uint32 _debug); + public static extern void set_debug(uint32 _debug, FrameBufferHandle _handle, uint8 _scale); /// /// Clear internal debug text buffer. @@ -4082,7 +4139,7 @@ public static class bgfx public static extern FrameBufferHandle create_frame_buffer_from_attachment(uint8 _num, Attachment* _attachment, bool _destroyTexture); /// - /// Create frame buffer for multiple window rendering. + /// Create a frame buffer for a window, from a full swap chain description. /// /// @remarks /// Frame buffer cannot be used for sampling. @@ -4091,14 +4148,27 @@ public static class bgfx /// /// /// - /// OS' target native window handle. - /// Window back buffer width. - /// Window back buffer height. - /// Window back buffer color format. - /// Window back buffer depth format. + /// Swap chain description. See: `bgfx::SwapChain`. /// - [LinkName("bgfx_create_frame_buffer_from_nwh")] - public static extern FrameBufferHandle create_frame_buffer_from_nwh(void* _nwh, uint16 _width, uint16 _height, TextureFormat _format, TextureFormat _depthFormat); + [LinkName("bgfx_create_frame_buffer_from_swap_chain")] + public static extern FrameBufferHandle create_frame_buffer_from_swap_chain(SwapChain* _desc); + + /// + /// Change a swap chain's size, format or per-surface flags, in place. + /// + /// The frame buffer handle stays valid, so nothing that refers to it has to be + /// rebuilt. Pass `BGFX_INVALID_HANDLE` to address the window bgfx was + /// initialized with. + /// + /// @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. + /// + /// + /// + /// Window frame buffer handle. The window bgfx was initialized with is not addressed here; it is `bgfx::reset`'s swap chain. + /// Swap chain description. See: `bgfx::SwapChain`. + /// + [LinkName("bgfx_update_swap_chain")] + public static extern void update_swap_chain(FrameBufferHandle _handle, SwapChain* _desc); /// /// Set frame buffer debug name. @@ -5223,18 +5293,6 @@ public static class bgfx [LinkName("bgfx_render_frame")] public static extern RenderFrame render_frame(int32 _msecs); - /// - /// Set platform data. - /// - /// @warning Must be called before `bgfx::init`. - /// - /// - /// - /// Platform data. - /// - [LinkName("bgfx_set_platform_data")] - public static extern void set_platform_data(PlatformData* _data); - /// /// Get internal data for interop. /// @@ -5248,48 +5306,6 @@ public static class bgfx [LinkName("bgfx_get_internal_data")] public static extern InternalData* get_internal_data(); - /// - /// Override internal texture with externally created texture. Previously - /// created internal texture will released. - /// - /// @attention It's expected you understand some bgfx internals before you - /// use this call. - /// - /// @warning Must be called only on render thread. - /// - /// - /// - /// Texture handle. - /// Native API pointer to texture. - /// Layer index for texture arrays (only implemented for D3D11). - /// - [LinkName("bgfx_override_internal_texture_ptr")] - public static extern void* override_internal_texture_ptr(TextureHandle _handle, void* _ptr, uint16 _layerIndex); - - /// - /// Override internal texture by creating new texture. Previously created - /// internal texture will released. - /// - /// @attention It's expected you understand some bgfx internals before you - /// use this call. - /// - /// @returns Native API pointer to texture. If result is 0, texture is not created yet from the - /// main thread. - /// - /// @warning Must be called only on render thread. - /// - /// - /// - /// Texture handle. - /// Width. - /// Height. - /// Number of mip-maps. - /// Texture format. See: `TextureFormat::Enum`. - /// Texture creation (see `BGFX_TEXTURE_*`.), and sampler (see `BGFX_SAMPLER_*`) flags. Default texture sampling mode is linear, and wrap mode is repeat. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. - /// - [LinkName("bgfx_override_internal_texture")] - public static extern void* override_internal_texture(TextureHandle _handle, uint16 _width, uint16 _height, uint8 _numMips, TextureFormat _format, uint64 _flags); - /// /// Sets a debug marker. This allows you to group graphics calls together for easy browsing in /// graphics debugging tools. diff --git a/bindings/c3/bgfx.c3 b/bindings/c3/bgfx.c3 index abea6cfb1..78c0189e1 100644 --- a/bindings/c3/bgfx.c3 +++ b/bindings/c3/bgfx.c3 @@ -611,6 +611,43 @@ constdef ResetFlags : inline uint RESERVEDMASK = 0x80000000, } +constdef SwapChainFlags : inline uint +{ + // Enable 2x MSAA. + MSAAX2 = 0x00000010, + + // Enable 4x MSAA. + MSAAX4 = 0x00000020, + + // Enable 8x MSAA. + MSAAX8 = 0x00000030, + + // Enable 16x MSAA. + MSAAX16 = 0x00000040, + MSAASHIFT = 4, + MSAAMASK = 0x00000070, + + // No swap chain flags. + NONE = 0x00000000, + + // Not supported yet. + FULLSCREEN = 0x00000001, + + // Enable sRGB backbuffer. + SRGBBACKBUFFER = 0x00008000, + + // Enable HDR10 rendering. + HDR10 = 0x00010000, + + // Enable HiDPI rendering. + HIDPI = 0x00020000, + + // Transparent backbuffer. Availability depends on: `BGFX_CAPS_TRANSPARENT_BACKBUFFER`. + TRANSPARENTBACKBUFFER = 0x00100000, + FULLSCREENSHIFT = 0, + FULLSCREENMASK = 0x00000001, +} + constdef CapsFlags : inline ulong { // Alpha to coverage is supported. @@ -868,7 +905,7 @@ constdef PciIdFlags : inline ushort // Intel adapter. INTEL = 0x8086, - // nVidia adapter. + // NVIDIA adapter. NVIDIA = 0x10de, // Microsoft adapter. @@ -1448,22 +1485,22 @@ enum UniformFreq : uint enum BackbufferRatio : uint { - // Equal to backbuffer. + // Equal to the main window's backbuffer. EQUAL, - // One half size of backbuffer. + // One half size of the main window's backbuffer. HALF, - // One quarter size of backbuffer. + // One quarter size of the main window's backbuffer. QUARTER, - // One eighth size of backbuffer. + // One eighth size of the main window's backbuffer. EIGHTH, - // One sixteenth size of backbuffer. + // One sixteenth size of the main window's backbuffer. SIXTEENTH, - // Double size of backbuffer. + // Double size of the main window's backbuffer. DOUBLE, COUNT @@ -1774,45 +1811,44 @@ struct InternalData // Platform data. struct PlatformData { - // Native display type (*nix specific). - void* ndt; - // Native window handle. If `NULL`, bgfx will create a headless - // context/device, provided the rendering API supports it. - void* nwh; // GL context, D3D device, or Vulkan device. If `NULL`, bgfx // will create context/device. void* context; // D3D12 Queue. If `NULL` bgfx will create queue. void* queue; - // GL back-buffer, or D3D render target view. If `NULL` bgfx will - // create back-buffer color surface. - void* backBuffer; - // Backbuffer depth/stencil. If `NULL`, bgfx will create a back-buffer - // depth/stencil surface. - void* backBufferDS; // Handle type. Needed for platforms having more than one option. NativeWindowHandleType type; } -// Backbuffer resolution and reset parameters. -struct Resolution +// Swap chain description. +struct SwapChain { - // Backbuffer color format. - TextureFormat formatColor; - // Backbuffer depth/stencil format. - TextureFormat formatDepthStencil; - // Backbuffer width. + // Native window handle. If `NULL`, bgfx will create a headless + // context/device, provided the rendering API supports it. + void* nwh; + // Native display type (*nix specific). A window that leaves this + // `NULL` uses the one the main window was initialized with. + void* ndt; + // Swap chain width. uint width; - // Backbuffer height. + // Swap chain height. uint height; - // Reset parameters. - uint reset; + // See: `BGFX_SWAP_CHAIN_*`. + uint flags; + // Color format. + TextureFormat formatColor; + // Depth/stencil format, or `TextureFormat::Count` for no depth. Ignored + // when `depth` is valid. + TextureFormat formatDepthStencil; + // Depth attachment. Must be created with `BGFX_TEXTURE_RT`, and match the + // swap chain width, height and sample count. When invalid, bgfx creates and + // owns a depth surface per `formatDepthStencil`. A texture supplied here is + // never destroyed by bgfx, and may be shared by several same-size swap chains. + TextureHandle depth; // Number of back buffers. char numBackBuffers; // Maximum frame latency. char maxFrameLatency; - // Scale factor for debug text. - char debugTextScale; } // Configurable runtime limits parameters. @@ -1880,8 +1916,13 @@ struct Init bool videoDecode; // Platform data. PlatformData platformData; - // Backbuffer resolution and reset parameters. See: `bgfx::Resolution`. - Resolution resolution; + // Swap chain for the window bgfx creates its device on. + // See: `bgfx::SwapChain`. + SwapChain swapChain; + // Device and frame global settings. Anything that is a + // property of one surface belongs in `swapChain` instead. + // See: `BGFX_RESET_*`. + uint reset; // Configurable runtime limits parameters. InitLimits limits; // Provide application specific callback interface. @@ -2469,11 +2510,9 @@ extern fn void shutdown() @cname("bgfx_shutdown"); // @attention This call doesn’t change the window size, it just resizes // the back-buffer. Your windowing code controls the window size. // -// _width : `Back-buffer width.` -// _height : `Back-buffer height.` -// _flags : `See: `BGFX_RESET_*` for more info. - `BGFX_RESET_NONE` - No reset flags. - `BGFX_RESET_FULLSCREEN` - Not supported yet. - `BGFX_RESET_MSAA_X[2/4/8/16]` - Enable 2, 4, 8 or 16 x MSAA. - `BGFX_RESET_VSYNC` - Enable V-Sync. - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. - `BGFX_RESET_CAPTURE` - Begin screen capture. - `BGFX_RESET_FLUSH_AFTER_RENDER` - Flush rendering after submitting to GPU. - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip occurs. Default behaviour is that flip occurs before rendering new frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. - `BGFX_RESET_SRGB_BACKBUFFER` - Enable sRGB back-buffer.` -// _format : `Texture format. See: `TextureFormat::Enum`.` -extern fn void reset(uint _width, uint _height, uint _flags, TextureFormat _format) @cname("bgfx_reset"); +// _flags : `See: `BGFX_RESET_*` for more info. - `BGFX_RESET_NONE` - No reset flags. - `BGFX_RESET_VSYNC` - Enable V-Sync. - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. - `BGFX_RESET_CAPTURE` - Begin screen capture. - `BGFX_RESET_FLUSH_AFTER_RENDER` - Flush rendering after submitting to GPU. - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip occurs. Default behaviour is that flip occurs before rendering new frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. Per-surface settings are not here. `BGFX_SWAP_CHAIN_*` flags belong on `SwapChain::flags`, and are ignored if passed here.` +// _swapChain : `Main window swap chain. When `NULL` the main window is left untouched and only the device and frame globals above are applied, which is what an application driving its own swap chains wants. Otherwise the main window takes on this description: resize it, change its format, or change its per-surface flags. Fields left neutral keep their current value, and `nwh`/`ndt` are ignored -- main's are bgfx's own. Must be `NULL` when `bgfx::init` created no main window.` +extern fn void reset(uint _flags, SwapChain* _swapChain) @cname("bgfx_reset"); // Advance to next frame. This is the main frame-advancement call on the // API thread (the thread from which `bgfx::init` was called). @@ -2561,7 +2600,9 @@ extern fn Memory* make_ref_release(void* _data, uint _size, void* _releaseFn, vo // Set debug flags. // _debug : `Available flags: - `BGFX_DEBUG_IFH` - Infinitely fast hardware. When this flag is set all rendering calls will be skipped. This is useful when profiling to quickly assess potential bottlenecks between CPU and GPU. - `BGFX_DEBUG_PROFILER` - Enable profiler. - `BGFX_DEBUG_STATS` - Display internal statistics. - `BGFX_DEBUG_TEXT` - Display debug text. - `BGFX_DEBUG_WIREFRAME` - Wireframe rendering. All rendering primitives will be rendered as lines.` -extern fn void set_debug(uint _debug) @cname("bgfx_set_debug"); +// _handle : `Frame buffer the debug text and statistics are drawn on. Invalid handle selects the window bgfx was initialized with.` +// _scale : `Debug text scale factor. 0 is the same as 1.` +extern fn void set_debug(uint _debug, FrameBufferHandle _handle, char _scale) @cname("bgfx_set_debug"); // Clear internal debug text buffer. // _attr : `Background color.` @@ -2996,19 +3037,27 @@ extern fn FrameBufferHandle create_frame_buffer_from_handles(char _num, TextureH // _destroyTexture : `If true, textures will be destroyed when frame buffer is destroyed.` extern fn FrameBufferHandle create_frame_buffer_from_attachment(char _num, Attachment* _attachment, bool _destroyTexture) @cname("bgfx_create_frame_buffer_from_attachment"); -// Create frame buffer for multiple window rendering. +// Create a frame buffer for a window, from a full swap chain description. // // @remarks // Frame buffer cannot be used for sampling. // // @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. // -// _nwh : `OS' target native window handle.` -// _width : `Window back buffer width.` -// _height : `Window back buffer height.` -// _format : `Window back buffer color format.` -// _depthFormat : `Window back buffer depth format.` -extern fn FrameBufferHandle create_frame_buffer_from_nwh(void* _nwh, ushort _width, ushort _height, TextureFormat _format, TextureFormat _depthFormat) @cname("bgfx_create_frame_buffer_from_nwh"); +// _desc : `Swap chain description. See: `bgfx::SwapChain`.` +extern fn FrameBufferHandle create_frame_buffer_from_swap_chain(SwapChain* _desc) @cname("bgfx_create_frame_buffer_from_swap_chain"); + +// Change a swap chain's size, format or per-surface flags, in place. +// +// The frame buffer handle stays valid, so nothing that refers to it has to be +// rebuilt. Pass `BGFX_INVALID_HANDLE` to address the window bgfx was +// initialized with. +// +// @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. +// +// _handle : `Window frame buffer handle. The window bgfx was initialized with is not addressed here; it is `bgfx::reset`'s swap chain.` +// _desc : `Swap chain description. See: `bgfx::SwapChain`.` +extern fn void update_swap_chain(FrameBufferHandle _handle, SwapChain* _desc) @cname("bgfx_update_swap_chain"); // Set frame buffer debug name. // _handle : `Frame buffer handle.` @@ -3754,13 +3803,6 @@ extern fn void request_screen_shot(FrameBufferHandle _handle, ZString _filePath) // _msecs : `Timeout in milliseconds.` extern fn RenderFrame render_frame(int _msecs) @cname("bgfx_render_frame"); -// Set platform data. -// -// @warning Must be called before `bgfx::init`. -// -// _data : `Platform data.` -extern fn void set_platform_data(PlatformData* _data) @cname("bgfx_set_platform_data"); - // Get internal data for interop. // // @attention It's expected you understand some bgfx internals before you @@ -3770,38 +3812,6 @@ extern fn void set_platform_data(PlatformData* _data) @cname("bgfx_set_platform_ // extern fn InternalData* get_internal_data() @cname("bgfx_get_internal_data"); -// Override internal texture with externally created texture. Previously -// created internal texture will released. -// -// @attention It's expected you understand some bgfx internals before you -// use this call. -// -// @warning Must be called only on render thread. -// -// _handle : `Texture handle.` -// _ptr : `Native API pointer to texture.` -// _layerIndex : `Layer index for texture arrays (only implemented for D3D11).` -extern fn uptr override_internal_texture_ptr(TextureHandle _handle, uptr _ptr, ushort _layerIndex) @cname("bgfx_override_internal_texture_ptr"); - -// Override internal texture by creating new texture. Previously created -// internal texture will released. -// -// @attention It's expected you understand some bgfx internals before you -// use this call. -// -// @returns Native API pointer to texture. If result is 0, texture is not created yet from the -// main thread. -// -// @warning Must be called only on render thread. -// -// _handle : `Texture handle.` -// _width : `Width.` -// _height : `Height.` -// _numMips : `Number of mip-maps.` -// _format : `Texture format. See: `TextureFormat::Enum`.` -// _flags : `Texture creation (see `BGFX_TEXTURE_*`.), and sampler (see `BGFX_SAMPLER_*`) flags. Default texture sampling mode is linear, and wrap mode is repeat. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling.` -extern fn uptr override_internal_texture(TextureHandle _handle, ushort _width, ushort _height, char _numMips, TextureFormat _format, ulong _flags) @cname("bgfx_override_internal_texture"); - // Sets a debug marker. This allows you to group graphics calls together for easy browsing in // graphics debugging tools. // _name : `Marker name.` diff --git a/bindings/cs/bgfx.cs b/bindings/cs/bgfx.cs index 567a7a6f4..fc85a0ad4 100644 --- a/bindings/cs/bgfx.cs +++ b/bindings/cs/bgfx.cs @@ -958,6 +958,64 @@ public static partial class bgfx ReservedMask = 0x80000000, } + [Flags] + public enum SwapChainFlags : uint + { + /// + /// Enable 2x MSAA. + /// + MsaaX2 = 0x00000010, + + /// + /// Enable 4x MSAA. + /// + MsaaX4 = 0x00000020, + + /// + /// Enable 8x MSAA. + /// + MsaaX8 = 0x00000030, + + /// + /// Enable 16x MSAA. + /// + MsaaX16 = 0x00000040, + MsaaShift = 4, + MsaaMask = 0x00000070, + + /// + /// No swap chain flags. + /// + None = 0x00000000, + + /// + /// Not supported yet. + /// + Fullscreen = 0x00000001, + + /// + /// Enable sRGB backbuffer. + /// + SrgbBackbuffer = 0x00008000, + + /// + /// Enable HDR10 rendering. + /// + Hdr10 = 0x00010000, + + /// + /// Enable HiDPI rendering. + /// + Hidpi = 0x00020000, + + /// + /// Transparent backbuffer. Availability depends on: `BGFX_CAPS_TRANSPARENT_BACKBUFFER`. + /// + TransparentBackbuffer = 0x00100000, + FullscreenShift = 0, + FullscreenMask = 0x00000001, + } + [Flags] public enum CapsFlags : ulong { @@ -1373,7 +1431,7 @@ public static partial class bgfx Intel = 0x8086, /// - /// nVidia adapter. + /// NVIDIA adapter. /// Nvidia = 0x10de, @@ -2305,32 +2363,32 @@ public static partial class bgfx public enum BackbufferRatio { /// - /// Equal to backbuffer. + /// Equal to the main window's backbuffer. /// Equal, /// - /// One half size of backbuffer. + /// One half size of the main window's backbuffer. /// Half, /// - /// One quarter size of backbuffer. + /// One quarter size of the main window's backbuffer. /// Quarter, /// - /// One eighth size of backbuffer. + /// One eighth size of the main window's backbuffer. /// Eighth, /// - /// One sixteenth size of backbuffer. + /// One sixteenth size of the main window's backbuffer. /// Sixteenth, /// - /// Double size of backbuffer. + /// Double size of the main window's backbuffer. /// Double, @@ -2622,25 +2680,23 @@ public static partial class bgfx public unsafe struct PlatformData { - public void* ndt; - public void* nwh; public void* context; public void* queue; - public void* backBuffer; - public void* backBufferDS; public NativeWindowHandleType type; } - public unsafe struct Resolution + public unsafe struct SwapChain { - public TextureFormat formatColor; - public TextureFormat formatDepthStencil; + public void* nwh; + public void* ndt; public uint width; public uint height; - public uint reset; + public uint flags; + public TextureFormat formatColor; + public TextureFormat formatDepthStencil; + public TextureHandle depth; public byte numBackBuffers; public byte maxFrameLatency; - public byte debugTextScale; } public unsafe struct Init @@ -2665,7 +2721,8 @@ public static partial class bgfx public byte fallback; public byte videoDecode; public PlatformData platformData; - public Resolution resolution; + public SwapChain swapChain; + public uint reset; public Limits limits; public IntPtr callback; public IntPtr allocator; @@ -3163,13 +3220,11 @@ public static partial class bgfx /// /// /// - /// Back-buffer width. - /// Back-buffer height. - /// See: `BGFX_RESET_*` for more info. - `BGFX_RESET_NONE` - No reset flags. - `BGFX_RESET_FULLSCREEN` - Not supported yet. - `BGFX_RESET_MSAA_X[2/4/8/16]` - Enable 2, 4, 8 or 16 x MSAA. - `BGFX_RESET_VSYNC` - Enable V-Sync. - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. - `BGFX_RESET_CAPTURE` - Begin screen capture. - `BGFX_RESET_FLUSH_AFTER_RENDER` - Flush rendering after submitting to GPU. - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip occurs. Default behaviour is that flip occurs before rendering new frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. - `BGFX_RESET_SRGB_BACKBUFFER` - Enable sRGB back-buffer. - /// Texture format. See: `TextureFormat::Enum`. + /// See: `BGFX_RESET_*` for more info. - `BGFX_RESET_NONE` - No reset flags. - `BGFX_RESET_VSYNC` - Enable V-Sync. - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. - `BGFX_RESET_CAPTURE` - Begin screen capture. - `BGFX_RESET_FLUSH_AFTER_RENDER` - Flush rendering after submitting to GPU. - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip occurs. Default behaviour is that flip occurs before rendering new frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. Per-surface settings are not here. `BGFX_SWAP_CHAIN_*` flags belong on `SwapChain::flags`, and are ignored if passed here. + /// Main window swap chain. When `NULL` the main window is left untouched and only the device and frame globals above are applied, which is what an application driving its own swap chains wants. Otherwise the main window takes on this description: resize it, change its format, or change its per-surface flags. Fields left neutral keep their current value, and `nwh`/`ndt` are ignored -- main's are bgfx's own. Must be `NULL` when `bgfx::init` created no main window. /// [DllImport(DllName, EntryPoint="bgfx_reset", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe void reset(uint _width, uint _height, uint _flags, TextureFormat _format); + public static extern unsafe void reset(uint _flags, SwapChain* _swapChain); /// /// Advance to next frame. This is the main frame-advancement call on the @@ -3297,9 +3352,11 @@ public static partial class bgfx /// /// /// Available flags: - `BGFX_DEBUG_IFH` - Infinitely fast hardware. When this flag is set all rendering calls will be skipped. This is useful when profiling to quickly assess potential bottlenecks between CPU and GPU. - `BGFX_DEBUG_PROFILER` - Enable profiler. - `BGFX_DEBUG_STATS` - Display internal statistics. - `BGFX_DEBUG_TEXT` - Display debug text. - `BGFX_DEBUG_WIREFRAME` - Wireframe rendering. All rendering primitives will be rendered as lines. + /// Frame buffer the debug text and statistics are drawn on. Invalid handle selects the window bgfx was initialized with. + /// Debug text scale factor. 0 is the same as 1. /// [DllImport(DllName, EntryPoint="bgfx_set_debug", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe void set_debug(uint _debug); + public static extern unsafe void set_debug(uint _debug, FrameBufferHandle _handle, byte _scale); /// /// Clear internal debug text buffer. @@ -4029,7 +4086,7 @@ public static partial class bgfx public static extern unsafe FrameBufferHandle create_frame_buffer_from_attachment(byte _num, Attachment* _attachment, bool _destroyTexture); /// - /// Create frame buffer for multiple window rendering. + /// Create a frame buffer for a window, from a full swap chain description. /// /// @remarks /// Frame buffer cannot be used for sampling. @@ -4038,14 +4095,27 @@ public static partial class bgfx /// /// /// - /// OS' target native window handle. - /// Window back buffer width. - /// Window back buffer height. - /// Window back buffer color format. - /// Window back buffer depth format. + /// Swap chain description. See: `bgfx::SwapChain`. /// - [DllImport(DllName, EntryPoint="bgfx_create_frame_buffer_from_nwh", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe FrameBufferHandle create_frame_buffer_from_nwh(void* _nwh, ushort _width, ushort _height, TextureFormat _format, TextureFormat _depthFormat); + [DllImport(DllName, EntryPoint="bgfx_create_frame_buffer_from_swap_chain", CallingConvention = CallingConvention.Cdecl)] + public static extern unsafe FrameBufferHandle create_frame_buffer_from_swap_chain(SwapChain* _desc); + + /// + /// Change a swap chain's size, format or per-surface flags, in place. + /// + /// The frame buffer handle stays valid, so nothing that refers to it has to be + /// rebuilt. Pass `BGFX_INVALID_HANDLE` to address the window bgfx was + /// initialized with. + /// + /// @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. + /// + /// + /// + /// Window frame buffer handle. The window bgfx was initialized with is not addressed here; it is `bgfx::reset`'s swap chain. + /// Swap chain description. See: `bgfx::SwapChain`. + /// + [DllImport(DllName, EntryPoint="bgfx_update_swap_chain", CallingConvention = CallingConvention.Cdecl)] + public static extern unsafe void update_swap_chain(FrameBufferHandle _handle, SwapChain* _desc); /// /// Set frame buffer debug name. @@ -5170,18 +5240,6 @@ public static partial class bgfx [DllImport(DllName, EntryPoint="bgfx_render_frame", CallingConvention = CallingConvention.Cdecl)] public static extern unsafe RenderFrame render_frame(int _msecs); - /// - /// Set platform data. - /// - /// @warning Must be called before `bgfx::init`. - /// - /// - /// - /// Platform data. - /// - [DllImport(DllName, EntryPoint="bgfx_set_platform_data", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe void set_platform_data(PlatformData* _data); - /// /// Get internal data for interop. /// @@ -5195,48 +5253,6 @@ public static partial class bgfx [DllImport(DllName, EntryPoint="bgfx_get_internal_data", CallingConvention = CallingConvention.Cdecl)] public static extern unsafe InternalData* get_internal_data(); - /// - /// Override internal texture with externally created texture. Previously - /// created internal texture will released. - /// - /// @attention It's expected you understand some bgfx internals before you - /// use this call. - /// - /// @warning Must be called only on render thread. - /// - /// - /// - /// Texture handle. - /// Native API pointer to texture. - /// Layer index for texture arrays (only implemented for D3D11). - /// - [DllImport(DllName, EntryPoint="bgfx_override_internal_texture_ptr", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe UIntPtr override_internal_texture_ptr(TextureHandle _handle, UIntPtr _ptr, ushort _layerIndex); - - /// - /// Override internal texture by creating new texture. Previously created - /// internal texture will released. - /// - /// @attention It's expected you understand some bgfx internals before you - /// use this call. - /// - /// @returns Native API pointer to texture. If result is 0, texture is not created yet from the - /// main thread. - /// - /// @warning Must be called only on render thread. - /// - /// - /// - /// Texture handle. - /// Width. - /// Height. - /// Number of mip-maps. - /// Texture format. See: `TextureFormat::Enum`. - /// Texture creation (see `BGFX_TEXTURE_*`.), and sampler (see `BGFX_SAMPLER_*`) flags. Default texture sampling mode is linear, and wrap mode is repeat. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. - /// - [DllImport(DllName, EntryPoint="bgfx_override_internal_texture", CallingConvention = CallingConvention.Cdecl)] - public static extern unsafe UIntPtr override_internal_texture(TextureHandle _handle, ushort _width, ushort _height, byte _numMips, TextureFormat _format, ulong _flags); - /// /// Sets a debug marker. This allows you to group graphics calls together for easy browsing in /// graphics debugging tools. diff --git a/bindings/d/package.d b/bindings/d/package.d index de3618313..04bcc9844 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 = 157; +enum uint apiVersion = 158; alias ViewID = ushort; @@ -472,6 +472,32 @@ enum ResetReserved: ResetReserved_{ mask = 0x8000_0000, ///Internal bit mask } +alias SwapChainMSAA_ = uint; +enum SwapChainMSAA: SwapChainMSAA_{ + x2 = 0x0000_0010, ///Enable 2x MSAA. + x4 = 0x0000_0020, ///Enable 4x MSAA. + x8 = 0x0000_0030, ///Enable 8x MSAA. + x16 = 0x0000_0040, ///Enable 16x MSAA. + shift = 4, + mask = 0x0000_0070, +} + +alias SwapChain_ = uint; +enum SwapChain: SwapChain_{ + none = 0x0000_0000, ///No swap chain flags. + fullscreen = 0x0000_0001, ///Not supported yet. + srgbBackbuffer = 0x0000_8000, ///Enable sRGB backbuffer. + hdr10 = 0x0001_0000, ///Enable HDR10 rendering. + hiDPI = 0x0002_0000, ///Enable HiDPI rendering. + transparentBackbuffer = 0x0010_0000, ///Transparent backbuffer. Availability depends on: `BGFX_CAPS_TRANSPARENT_BACKBUFFER`. +} + +alias SwapChainFullscreen_ = uint; +enum SwapChainFullscreen: SwapChainFullscreen_{ + shift = 0, + mask = 0x0000_0001, +} + alias CapFlags_ = ulong; enum CapFlags: CapFlags_{ alphaToCoverage = 0x0000_0000_0000_0001, ///Alpha to coverage is supported. @@ -603,7 +629,7 @@ enum PCIID: PCIID_{ amd = 0x1002, ///AMD adapter. apple = 0x106B, ///Apple adapter. intel = 0x8086, ///Intel adapter. - nvidia = 0x10DE, ///nVidia adapter. + nvidia = 0x10DE, ///NVIDIA adapter. microsoft = 0x1414, ///Microsoft adapter. arm = 0x13B5, ///ARM adapter. } @@ -854,7 +880,15 @@ enum UniformFreq: bgfx.impl.UniformFreq.Enum{ count = bgfx.impl.UniformFreq.Enum.count, } -///Backbuffer ratio enum. +/** +Backbuffer ratio enum. + +The ratio is always relative to the window bgfx was initialized with, and is +re-resolved by `bgfx::reset`. It is not relative to whichever window a texture +happens to be rendered to, so on a second window a ratio texture is not +meaningfully sized. For that reason a ratio texture cannot be used as +`SwapChain::depth`. +*/ enum BackbufferRatio: bgfx.impl.BackbufferRatio.Enum{ equal = bgfx.impl.BackbufferRatio.Enum.equal, half = bgfx.impl.BackbufferRatio.Enum.half, @@ -1227,8 +1261,17 @@ extern(C++, "bgfx") struct InternalData{ ///Platform data. extern(C++, "bgfx") struct PlatformData{ - void* ndt; ///Native display type (*nix specific). - + /** + GL context, D3D device, or Vulkan device. If `NULL`, bgfx + will create context/device. + */ + void* context; + void* queue; ///D3D12 Queue. If `NULL` bgfx will create queue. + NativeWindowHandleType type; ///Handle type. Needed for platforms having more than one option. +} + +///Swap chain description. +extern(C++, "bgfx") struct SwapChain{ /** Native window handle. If `NULL`, bgfx will create a headless context/device, provided the rendering API supports it. @@ -1236,36 +1279,30 @@ extern(C++, "bgfx") struct PlatformData{ void* nwh; /** - GL context, D3D device, or Vulkan device. If `NULL`, bgfx - will create context/device. + Native display type (*nix specific). A window that leaves this + `NULL` uses the one the main window was initialized with. */ - void* context; - void* queue; ///D3D12 Queue. If `NULL` bgfx will create queue. + void* ndt; + uint width; ///Swap chain width. + uint height; ///Swap chain height. + uint flags; ///See: `BGFX_SWAP_CHAIN_*`. + TextureFormat formatColor; ///Color format. /** - GL back-buffer, or D3D render target view. If `NULL` bgfx will - create back-buffer color surface. + Depth/stencil format, or `TextureFormat::Count` for no depth. Ignored + when `depth` is valid. */ - void* backBuffer; + TextureFormat formatDepthStencil; /** - Backbuffer depth/stencil. If `NULL`, bgfx will create a back-buffer - depth/stencil surface. + Depth attachment. Must be created with `BGFX_TEXTURE_RT`, and match the + swap chain width, height and sample count. When invalid, bgfx creates and + owns a depth surface per `formatDepthStencil`. A texture supplied here is + never destroyed by bgfx, and may be shared by several same-size swap chains. */ - void* backBufferDS; - NativeWindowHandleType type; ///Handle type. Needed for platforms having more than one option. -} - -///Backbuffer resolution and reset parameters. -extern(C++, "bgfx") struct Resolution{ - TextureFormat formatColor; ///Backbuffer color format. - TextureFormat formatDepthStencil; ///Backbuffer depth/stencil format. - uint width; ///Backbuffer width. - uint height; ///Backbuffer height. - uint reset; ///Reset parameters. + TextureHandle depth; ubyte numBackBuffers; ///Number of back buffers. ubyte maxFrameLatency; ///Maximum frame latency. - ubyte debugTextScale; ///Scale factor for debug text. extern(D) mixin(joinFnBinds((){ FnBind[] ret = [ {q{void}, q{this}, q{}, ext: `C++`}, @@ -1346,7 +1383,19 @@ extern(C++, "bgfx") struct Init{ bool fallback; ///Enable fallback to next available renderer. bool videoDecode; ///Enable video decoding. PlatformData platformData; ///Platform data. - Resolution resolution; ///Backbuffer resolution and reset parameters. See: `bgfx::Resolution`. + + /** + Swap chain for the window bgfx creates its device on. + See: `bgfx::SwapChain`. + */ + SwapChain swapChain; + + /** + Device and frame global settings. Anything that is a + property of one surface belongs in `swapChain` instead. + See: `BGFX_RESET_*`. + */ + uint reset; Limits limits; ///Configurable runtime limits parameters. /** @@ -2480,12 +2529,8 @@ mixin(joinFnBinds((){ * the back-buffer. Your windowing code controls the window size. * Params: - width = Back-buffer width. - height = Back-buffer height. flags = See: `BGFX_RESET_*` for more info. - `BGFX_RESET_NONE` - No reset flags. - - `BGFX_RESET_FULLSCREEN` - Not supported yet. - - `BGFX_RESET_MSAA_X[2/4/8/16]` - Enable 2, 4, 8 or 16 x MSAA. - `BGFX_RESET_VSYNC` - Enable V-Sync. - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. - `BGFX_RESET_CAPTURE` - Begin screen capture. @@ -2493,10 +2538,18 @@ mixin(joinFnBinds((){ - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip occurs. Default behaviour is that flip occurs before rendering new frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. - - `BGFX_RESET_SRGB_BACKBUFFER` - Enable sRGB back-buffer. - format = Texture format. See: `TextureFormat::Enum`. + Per-surface settings are not here. `BGFX_SWAP_CHAIN_*` flags belong + on `SwapChain::flags`, and are ignored if passed here. + swapChain = Main window swap chain. When `NULL` the main window is left + untouched and only the device and frame globals above are + applied, which is what an application driving its own swap + chains wants. Otherwise the main window takes on this + description: resize it, change its format, or change its + per-surface flags. Fields left neutral keep their current + value, and `nwh`/`ndt` are ignored -- main's are bgfx's own. + Must be `NULL` when `bgfx::init` created no main window. */ - {q{void}, q{reset}, q{uint width, uint height, uint flags=Reset.none, bgfx.impl.TextureFormat.Enum format=TextureFormat.count}, ext: `C++, "bgfx"`}, + {q{void}, q{reset}, q{uint flags=Reset.none, const(SwapChain)* swapChain=null}, ext: `C++, "bgfx"`}, /** * Advance to next frame. This is the main frame-advancement call on the @@ -2589,8 +2642,11 @@ mixin(joinFnBinds((){ - `BGFX_DEBUG_TEXT` - Display debug text. - `BGFX_DEBUG_WIREFRAME` - Wireframe rendering. All rendering primitives will be rendered as lines. + handle = Frame buffer the debug text and statistics are drawn on. + Invalid handle selects the window bgfx was initialized with. + scale = Debug text scale factor. 0 is the same as 1. */ - {q{void}, q{setDebug}, q{uint debug_}, ext: `C++, "bgfx"`}, + {q{void}, q{setDebug}, q{uint debug_, FrameBufferHandle handle=invalidHandle!FrameBufferHandle, ubyte scale=0}, ext: `C++, "bgfx"`}, /** * Clear internal debug text buffer. @@ -3345,7 +3401,7 @@ mixin(joinFnBinds((){ {q{FrameBufferHandle}, q{createFrameBuffer}, q{ubyte num, const(Attachment)* attachment, bool destroyTexture=false}, ext: `C++, "bgfx"`}, /** - * Create frame buffer for multiple window rendering. + * Create a frame buffer for a window, from a full swap chain description. * * Remarks: * Frame buffer cannot be used for sampling. @@ -3353,13 +3409,25 @@ mixin(joinFnBinds((){ * Attention: Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. * Params: - nwh = OS' target native window handle. - width = Window back buffer width. - height = Window back buffer height. - format = Window back buffer color format. - depthFormat = Window back buffer depth format. + desc = Swap chain description. See: `bgfx::SwapChain`. */ - {q{FrameBufferHandle}, q{createFrameBuffer}, q{void* nwh, ushort width, ushort height, bgfx.impl.TextureFormat.Enum format=TextureFormat.count, bgfx.impl.TextureFormat.Enum depthFormat=TextureFormat.count}, ext: `C++, "bgfx"`}, + {q{FrameBufferHandle}, q{createFrameBuffer}, q{ref const SwapChain desc}, ext: `C++, "bgfx"`}, + + /** + * Change a swap chain's size, format or per-surface flags, in place. + * + * The frame buffer handle stays valid, so nothing that refers to it has to be + * rebuilt. Pass `BGFX_INVALID_HANDLE` to address the window bgfx was + * initialized with. + * + * Attention: Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. + * + Params: + handle = Window frame buffer handle. The window bgfx was initialized + with is not addressed here; it is `bgfx::reset`'s swap chain. + desc = Swap chain description. See: `bgfx::SwapChain`. + */ + {q{void}, q{updateSwapChain}, q{FrameBufferHandle handle, ref const SwapChain desc}, ext: `C++, "bgfx"`}, /** * Set frame buffer debug name. @@ -3813,16 +3881,6 @@ mixin(joinFnBinds((){ */ {q{RenderFrame}, q{renderFrame}, q{int msecs=-1}, ext: `C++, "bgfx"`}, - /** - * Set platform data. - * - * Warning: Must be called before `bgfx::init`. - * - Params: - data = Platform data. - */ - {q{void}, q{setPlatformData}, q{ref const PlatformData data}, ext: `C++, "bgfx"`}, - /** * Get internal data for interop. * @@ -3834,49 +3892,6 @@ mixin(joinFnBinds((){ */ {q{const(InternalData)*}, q{getInternalData}, q{}, ext: `C++, "bgfx"`}, - /** - * Override internal texture with externally created texture. Previously - * created internal texture will released. - * - * Attention: It's expected you understand some bgfx internals before you - * use this call. - * - * Warning: Must be called only on render thread. - * - Params: - handle = Texture handle. - ptr = Native API pointer to texture. - layerIndex = Layer index for texture arrays (only implemented for D3D11). - */ - {q{size_t}, q{overrideInternal}, q{TextureHandle handle, size_t ptr, ushort layerIndex=0}, ext: `C++, "bgfx"`}, - - /** - * Override internal texture by creating new texture. Previously created - * internal texture will released. - * - * Attention: It's expected you understand some bgfx internals before you - * use this call. - * - * Returns: Native API pointer to texture. If result is 0, texture is not created yet from the - * main thread. - * - * Warning: Must be called only on render thread. - * - Params: - handle = Texture handle. - width = Width. - height = Height. - numMIPs = Number of mip-maps. - format = Texture format. See: `TextureFormat::Enum`. - flags = Texture creation (see `BGFX_TEXTURE_*`.), and sampler (see `BGFX_SAMPLER_*`) - flags. Default texture sampling mode is linear, and wrap mode is repeat. - - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap - mode. - - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic - sampling. - */ - {q{size_t}, q{overrideInternal}, q{TextureHandle handle, ushort width, ushort height, ubyte numMIPs, bgfx.impl.TextureFormat.Enum format, c_uint64 flags=Texture.none | Sampler.none}, ext: `C++, "bgfx"`}, - /** * Sets a debug marker. This allows you to group graphics calls together for easy browsing in * graphics debugging tools. @@ -4464,7 +4479,7 @@ mixin(joinFnBinds((){ ]; return ret; -}(), "Resolution, Init.Limits, Init, TextureRegion, BufferRegion, Attachment, VertexLayout, Encoder, ")); +}(), "SwapChain, Init.Limits, Init, TextureRegion, BufferRegion, Attachment, VertexLayout, Encoder, ")); static if(!staticBinding): import bindbc.loader; diff --git a/bindings/py/bgfx.py b/bindings/py/bgfx.py index 71570b160..58e0148f4 100644 --- a/bindings/py/bgfx.py +++ b/bindings/py/bgfx.py @@ -536,6 +536,26 @@ class DebugFlags(enum.IntFlag): Text = 0x8 Profiler = 0x10 +class SwapChainMsaaFlags(enum.IntFlag): + X2 = 0x10 + X4 = 0x20 + X8 = 0x30 + X16 = 0x40 + Shift = 0x4 + Mask = 0x70 + +class SwapChainFlags(enum.IntFlag): + None_ = 0x0 + Fullscreen = 0x1 + SrgbBackbuffer = 0x8000 + Hdr10 = 0x10000 + Hidpi = 0x20000 + TransparentBackbuffer = 0x100000 + +class SwapChainFullscreenFlags(enum.IntFlag): + Shift = 0x0 + Mask = 0x1 + class CapsFlags(enum.IntFlag): AlphaToCoverage = 0x1 BlendIndependent = 0x2 @@ -658,7 +678,7 @@ class InternalData(ctypes.Structure): class PlatformData(ctypes.Structure): pass -class Resolution(ctypes.Structure): +class SwapChain(ctypes.Structure): pass class InitLimits(ctypes.Structure): @@ -871,24 +891,22 @@ InternalData._fields_ = [ ] PlatformData._fields_ = [ - ("ndt", ctypes.c_void_p), - ("nwh", ctypes.c_void_p), ("context", ctypes.c_void_p), ("queue", ctypes.c_void_p), - ("backBuffer", ctypes.c_void_p), - ("backBufferDS", ctypes.c_void_p), ("type", ctypes.c_int), ] -Resolution._fields_ = [ - ("formatColor", ctypes.c_int), - ("formatDepthStencil", ctypes.c_int), +SwapChain._fields_ = [ + ("nwh", ctypes.c_void_p), + ("ndt", ctypes.c_void_p), ("width", ctypes.c_uint32), ("height", ctypes.c_uint32), - ("reset", ctypes.c_uint32), + ("flags", ctypes.c_uint32), + ("formatColor", ctypes.c_int), + ("formatDepthStencil", ctypes.c_int), + ("depth", TextureHandle), ("numBackBuffers", ctypes.c_uint8), ("maxFrameLatency", ctypes.c_uint8), - ("debugTextScale", ctypes.c_uint8), ] InitLimits._fields_ = [ @@ -911,7 +929,8 @@ Init._fields_ = [ ("fallback", ctypes.c_bool), ("videoDecode", ctypes.c_bool), ("platformData", PlatformData), - ("resolution", Resolution), + ("swapChain", SwapChain), + ("reset", ctypes.c_uint32), ("limits", InitLimits), ("callback", ctypes.c_void_p), ("allocator", ctypes.c_void_p), @@ -1176,7 +1195,7 @@ def _bind(lib): bgfx_shutdown.restype = None global bgfx_reset bgfx_reset = lib.bgfx_reset - bgfx_reset.argtypes = [ctypes.c_uint32, ctypes.c_uint32, ctypes.c_uint32, ctypes.c_int] + bgfx_reset.argtypes = [ctypes.c_uint32, ctypes.POINTER(SwapChain)] bgfx_reset.restype = None global bgfx_frame bgfx_frame = lib.bgfx_frame @@ -1212,7 +1231,7 @@ def _bind(lib): bgfx_make_ref_release.restype = ctypes.POINTER(Memory) global bgfx_set_debug bgfx_set_debug = lib.bgfx_set_debug - bgfx_set_debug.argtypes = [ctypes.c_uint32] + bgfx_set_debug.argtypes = [ctypes.c_uint32, FrameBufferHandle, ctypes.c_uint8] bgfx_set_debug.restype = None global bgfx_dbg_text_clear bgfx_dbg_text_clear = lib.bgfx_dbg_text_clear @@ -1442,10 +1461,14 @@ def _bind(lib): bgfx_create_frame_buffer_from_attachment = lib.bgfx_create_frame_buffer_from_attachment bgfx_create_frame_buffer_from_attachment.argtypes = [ctypes.c_uint8, ctypes.POINTER(Attachment), ctypes.c_bool] bgfx_create_frame_buffer_from_attachment.restype = FrameBufferHandle - global bgfx_create_frame_buffer_from_nwh - bgfx_create_frame_buffer_from_nwh = lib.bgfx_create_frame_buffer_from_nwh - bgfx_create_frame_buffer_from_nwh.argtypes = [ctypes.c_void_p, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_int, ctypes.c_int] - bgfx_create_frame_buffer_from_nwh.restype = FrameBufferHandle + global bgfx_create_frame_buffer_from_swap_chain + bgfx_create_frame_buffer_from_swap_chain = lib.bgfx_create_frame_buffer_from_swap_chain + bgfx_create_frame_buffer_from_swap_chain.argtypes = [ctypes.POINTER(SwapChain)] + bgfx_create_frame_buffer_from_swap_chain.restype = FrameBufferHandle + global bgfx_update_swap_chain + bgfx_update_swap_chain = lib.bgfx_update_swap_chain + bgfx_update_swap_chain.argtypes = [FrameBufferHandle, ctypes.POINTER(SwapChain)] + bgfx_update_swap_chain.restype = None global bgfx_set_frame_buffer_name bgfx_set_frame_buffer_name = lib.bgfx_set_frame_buffer_name bgfx_set_frame_buffer_name.argtypes = [FrameBufferHandle, ctypes.c_char_p, ctypes.c_int32] @@ -1750,22 +1773,10 @@ def _bind(lib): bgfx_render_frame = lib.bgfx_render_frame bgfx_render_frame.argtypes = [ctypes.c_int32] bgfx_render_frame.restype = ctypes.c_int - global bgfx_set_platform_data - bgfx_set_platform_data = lib.bgfx_set_platform_data - bgfx_set_platform_data.argtypes = [ctypes.POINTER(PlatformData)] - bgfx_set_platform_data.restype = None global bgfx_get_internal_data bgfx_get_internal_data = lib.bgfx_get_internal_data bgfx_get_internal_data.argtypes = [] bgfx_get_internal_data.restype = ctypes.POINTER(InternalData) - global bgfx_override_internal_texture_ptr - bgfx_override_internal_texture_ptr = lib.bgfx_override_internal_texture_ptr - bgfx_override_internal_texture_ptr.argtypes = [TextureHandle, ctypes.c_size_t, ctypes.c_uint16] - bgfx_override_internal_texture_ptr.restype = ctypes.c_size_t - global bgfx_override_internal_texture - bgfx_override_internal_texture = lib.bgfx_override_internal_texture - bgfx_override_internal_texture.argtypes = [TextureHandle, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_uint8, ctypes.c_int, ctypes.c_uint64] - bgfx_override_internal_texture.restype = ctypes.c_size_t global bgfx_set_marker bgfx_set_marker = lib.bgfx_set_marker bgfx_set_marker.argtypes = [ctypes.c_char_p, ctypes.c_int32] diff --git a/bindings/py/bgfx.pyi b/bindings/py/bgfx.pyi index 10ebfee6e..99cfd909e 100644 --- a/bindings/py/bgfx.pyi +++ b/bindings/py/bgfx.pyi @@ -393,18 +393,24 @@ class UniformFreq(enum.IntEnum): Count = 3 # Backbuffer ratio enum. +# +# The ratio is always relative to the window bgfx was initialized with, and is +# re-resolved by `bgfx::reset`. It is not relative to whichever window a texture +# happens to be rendered to, so on a second window a ratio texture is not +# meaningfully sized. For that reason a ratio texture cannot be used as +# `SwapChain::depth`. class BackbufferRatio(enum.IntEnum): - # Equal to backbuffer. + # Equal to the main window's backbuffer. Equal = 0 - # One half size of backbuffer. + # One half size of the main window's backbuffer. Half = 1 - # One quarter size of backbuffer. + # One quarter size of the main window's backbuffer. Quarter = 2 - # One eighth size of backbuffer. + # One eighth size of the main window's backbuffer. Eighth = 3 - # One sixteenth size of backbuffer. + # One sixteenth size of the main window's backbuffer. Sixteenth = 4 - # Double size of backbuffer. + # Double size of the main window's backbuffer. Double = 5 Count = 6 @@ -973,6 +979,36 @@ class DebugFlags(enum.IntFlag): # Enable profiler. This causes per-view statistics to be collected, available through `bgfx::Stats::ViewStats`. This is unrelated to the profiler functions in `bgfx::CallbackI`. Profiler = 0x10 +class SwapChainMsaaFlags(enum.IntFlag): + # Enable 2x MSAA. + X2 = 0x10 + # Enable 4x MSAA. + X4 = 0x20 + # Enable 8x MSAA. + X8 = 0x30 + # Enable 16x MSAA. + X16 = 0x40 + Shift = 0x4 + Mask = 0x70 + +class SwapChainFlags(enum.IntFlag): + # No swap chain flags. + None_ = 0x0 + # Not supported yet. + Fullscreen = 0x1 + # Enable sRGB backbuffer. + SrgbBackbuffer = 0x8000 + # Enable HDR10 rendering. + Hdr10 = 0x10000 + # Enable HiDPI rendering. + Hidpi = 0x20000 + # Transparent backbuffer. Availability depends on: `BGFX_CAPS_TRANSPARENT_BACKBUFFER`. + TransparentBackbuffer = 0x100000 + +class SwapChainFullscreenFlags(enum.IntFlag): + Shift = 0x0 + Mask = 0x1 + class CapsFlags(enum.IntFlag): # Alpha to coverage is supported. AlphaToCoverage = 0x1 @@ -1148,7 +1184,7 @@ class PciIdFlags(enum.IntFlag): Apple = 0x106b # Intel adapter. Intel = 0x8086 - # nVidia adapter. + # NVIDIA adapter. Nvidia = 0x10de # Microsoft adapter. Microsoft = 0x1414 @@ -1318,43 +1354,42 @@ class InternalData(ctypes.Structure): # Platform data. class PlatformData(ctypes.Structure): - # Native display type (*nix specific). - ndt: Any - # Native window handle. If `NULL`, bgfx will create a headless - # context/device, provided the rendering API supports it. - nwh: Any # GL context, D3D device, or Vulkan device. If `NULL`, bgfx # will create context/device. context: Any # D3D12 Queue. If `NULL` bgfx will create queue. queue: Any - # GL back-buffer, or D3D render target view. If `NULL` bgfx will - # create back-buffer color surface. - backBuffer: Any - # Backbuffer depth/stencil. If `NULL`, bgfx will create a back-buffer - # depth/stencil surface. - backBufferDS: Any # Handle type. Needed for platforms having more than one option. type: int -# Backbuffer resolution and reset parameters. -class Resolution(ctypes.Structure): - # Backbuffer color format. - formatColor: int - # Backbuffer depth/stencil format. - formatDepthStencil: int - # Backbuffer width. +# Swap chain description. +class SwapChain(ctypes.Structure): + # Native window handle. If `NULL`, bgfx will create a headless + # context/device, provided the rendering API supports it. + nwh: Any + # Native display type (*nix specific). A window that leaves this + # `NULL` uses the one the main window was initialized with. + ndt: Any + # Swap chain width. width: int - # Backbuffer height. + # Swap chain height. height: int - # Reset parameters. - reset: int + # See: `BGFX_SWAP_CHAIN_*`. + flags: int + # Color format. + formatColor: int + # Depth/stencil format, or `TextureFormat::Count` for no depth. Ignored + # when `depth` is valid. + formatDepthStencil: int + # Depth attachment. Must be created with `BGFX_TEXTURE_RT`, and match the + # swap chain width, height and sample count. When invalid, bgfx creates and + # owns a depth surface per `formatDepthStencil`. A texture supplied here is + # never destroyed by bgfx, and may be shared by several same-size swap chains. + depth: TextureHandle # Number of back buffers. numBackBuffers: int # Maximum frame latency. maxFrameLatency: int - # Scale factor for debug text. - debugTextScale: int # Configurable runtime limits parameters. class InitLimits(ctypes.Structure): @@ -1418,8 +1453,13 @@ class Init(ctypes.Structure): videoDecode: bool # Platform data. platformData: PlatformData - # Backbuffer resolution and reset parameters. See: `bgfx::Resolution`. - resolution: Resolution + # Swap chain for the window bgfx creates its device on. + # See: `bgfx::SwapChain`. + swapChain: SwapChain + # Device and frame global settings. Anything that is a + # property of one surface belongs in `swapChain` instead. + # See: `BGFX_RESET_*`. + reset: int # Configurable runtime limits parameters. limits: InitLimits # Provide application specific callback interface. @@ -2001,7 +2041,7 @@ def bgfx_shutdown() -> None: ... # @attention This call doesn’t change the window size, it just resizes # the back-buffer. Your windowing code controls the window size. # -def bgfx_reset(_width: int, _height: int, _flags: int, _format: Union[TextureFormat, int], /) -> None: ... +def bgfx_reset(_flags: int, _swapChain: Optional[Union[SwapChain, _Pointer[SwapChain], ctypes.Array]], /) -> None: ... # Advance to next frame. This is the main frame-advancement call on the # API thread (the thread from which `bgfx::init` was called). @@ -2078,7 +2118,7 @@ def bgfx_make_ref(_data: Any, _size: int, /) -> _Pointer[Memory]: ... def bgfx_make_ref_release(_data: Any, _size: int, _releaseFn: Any, _userData: Any, /) -> _Pointer[Memory]: ... # Set debug flags. -def bgfx_set_debug(_debug: int, /) -> None: ... +def bgfx_set_debug(_debug: int, _handle: FrameBufferHandle, _scale: int, /) -> None: ... # Clear internal debug text buffer. def bgfx_dbg_text_clear(_attr: int, _small: bool, /) -> None: ... @@ -2412,14 +2452,24 @@ def bgfx_create_frame_buffer_from_handles(_num: int, _handles: Optional[Union[Te # mip level. def bgfx_create_frame_buffer_from_attachment(_num: int, _attachment: Optional[Union[Attachment, _Pointer[Attachment], ctypes.Array]], _destroyTexture: bool, /) -> FrameBufferHandle: ... -# Create frame buffer for multiple window rendering. +# Create a frame buffer for a window, from a full swap chain description. # # @remarks # Frame buffer cannot be used for sampling. # # @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. # -def bgfx_create_frame_buffer_from_nwh(_nwh: Any, _width: int, _height: int, _format: Union[TextureFormat, int], _depthFormat: Union[TextureFormat, int], /) -> FrameBufferHandle: ... +def bgfx_create_frame_buffer_from_swap_chain(_desc: Optional[Union[SwapChain, _Pointer[SwapChain], ctypes.Array]], /) -> FrameBufferHandle: ... + +# Change a swap chain's size, format or per-surface flags, in place. +# +# The frame buffer handle stays valid, so nothing that refers to it has to be +# rebuilt. Pass `BGFX_INVALID_HANDLE` to address the window bgfx was +# initialized with. +# +# @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. +# +def bgfx_update_swap_chain(_handle: FrameBufferHandle, _desc: Optional[Union[SwapChain, _Pointer[SwapChain], ctypes.Array]], /) -> None: ... # Set frame buffer debug name. def bgfx_set_frame_buffer_name(_handle: FrameBufferHandle, _name: Optional[bytes], _len: int, /) -> None: ... @@ -3035,12 +3085,6 @@ def bgfx_request_screen_shot(_handle: FrameBufferHandle, _filePath: Optional[byt # def bgfx_render_frame(_msecs: int, /) -> int: ... -# Set platform data. -# -# @warning Must be called before `bgfx::init`. -# -def bgfx_set_platform_data(_data: Optional[Union[PlatformData, _Pointer[PlatformData], ctypes.Array]], /) -> None: ... - # Get internal data for interop. # # @attention It's expected you understand some bgfx internals before you @@ -3050,37 +3094,6 @@ def bgfx_set_platform_data(_data: Optional[Union[PlatformData, _Pointer[Platform # def bgfx_get_internal_data() -> _Pointer[InternalData]: ... -# Override internal texture with externally created texture. Previously -# created internal texture will released. -# -# @attention It's expected you understand some bgfx internals before you -# use this call. -# -# @warning Must be called only on render thread. -# -def bgfx_override_internal_texture_ptr(_handle: TextureHandle, _ptr: int, _layerIndex: int, /) -> int: ... - -# Override internal texture by creating new texture. Previously created -# internal texture will released. -# -# @attention It's expected you understand some bgfx internals before you -# use this call. -# -# @returns Native API pointer to texture. If result is 0, texture is not created yet from the -# main thread. -# -# @warning Must be called only on render thread. -# -def bgfx_override_internal_texture( - _handle: TextureHandle, - _width: int, - _height: int, - _numMips: int, - _format: Union[TextureFormat, int], - _flags: int, - /, -) -> int: ... - # Sets a debug marker. This allows you to group graphics calls together for easy browsing in # graphics debugging tools. def bgfx_set_marker(_name: Optional[bytes], _len: int, /) -> None: ... diff --git a/bindings/zig/bgfx.zig b/bindings/zig/bgfx.zig index fa268ec90..77b475086 100644 --- a/bindings/zig/bgfx.zig +++ b/bindings/zig/bgfx.zig @@ -594,6 +594,41 @@ pub const ResetFlags_FullscreenMask: ResetFlags = 0x00000001; pub const ResetFlags_ReservedShift: ResetFlags = 31; pub const ResetFlags_ReservedMask: ResetFlags = 0x80000000; +pub const SwapChainFlags = u32; +/// Enable 2x MSAA. +pub const SwapChainFlags_MsaaX2: SwapChainFlags = 0x00000010; + +/// Enable 4x MSAA. +pub const SwapChainFlags_MsaaX4: SwapChainFlags = 0x00000020; + +/// Enable 8x MSAA. +pub const SwapChainFlags_MsaaX8: SwapChainFlags = 0x00000030; + +/// Enable 16x MSAA. +pub const SwapChainFlags_MsaaX16: SwapChainFlags = 0x00000040; +pub const SwapChainFlags_MsaaShift: SwapChainFlags = 4; +pub const SwapChainFlags_MsaaMask: SwapChainFlags = 0x00000070; + +/// No swap chain flags. +pub const SwapChainFlags_None: SwapChainFlags = 0x00000000; + +/// Not supported yet. +pub const SwapChainFlags_Fullscreen: SwapChainFlags = 0x00000001; + +/// Enable sRGB backbuffer. +pub const SwapChainFlags_SrgbBackbuffer: SwapChainFlags = 0x00008000; + +/// Enable HDR10 rendering. +pub const SwapChainFlags_Hdr10: SwapChainFlags = 0x00010000; + +/// Enable HiDPI rendering. +pub const SwapChainFlags_Hidpi: SwapChainFlags = 0x00020000; + +/// Transparent backbuffer. Availability depends on: `BGFX_CAPS_TRANSPARENT_BACKBUFFER`. +pub const SwapChainFlags_TransparentBackbuffer: SwapChainFlags = 0x00100000; +pub const SwapChainFlags_FullscreenShift: SwapChainFlags = 0; +pub const SwapChainFlags_FullscreenMask: SwapChainFlags = 0x00000001; + pub const CapsFlags = u64; /// Alpha to coverage is supported. pub const CapsFlags_AlphaToCoverage: CapsFlags = 0x0000000000000001; @@ -838,7 +873,7 @@ pub const PciIdFlags_Apple: PciIdFlags = 0x106b; /// Intel adapter. pub const PciIdFlags_Intel: PciIdFlags = 0x8086; -/// nVidia adapter. +/// NVIDIA adapter. pub const PciIdFlags_Nvidia: PciIdFlags = 0x10de; /// Microsoft adapter. @@ -1404,22 +1439,22 @@ pub const UniformFreq = enum(c_int) { }; pub const BackbufferRatio = enum(c_int) { - /// Equal to backbuffer. + /// Equal to the main window's backbuffer. Equal, - /// One half size of backbuffer. + /// One half size of the main window's backbuffer. Half, - /// One quarter size of backbuffer. + /// One quarter size of the main window's backbuffer. Quarter, - /// One eighth size of backbuffer. + /// One eighth size of the main window's backbuffer. Eighth, - /// One sixteenth size of backbuffer. + /// One sixteenth size of the main window's backbuffer. Sixteenth, - /// Double size of backbuffer. + /// Double size of the main window's backbuffer. Double, Count @@ -1630,24 +1665,22 @@ pub const Caps = extern struct { }; pub const PlatformData = extern struct { - ndt: ?*anyopaque, - nwh: ?*anyopaque, context: ?*anyopaque, queue: ?*anyopaque, - backBuffer: ?*anyopaque, - backBufferDS: ?*anyopaque, type: NativeWindowHandleType, }; - pub const Resolution = extern struct { - formatColor: TextureFormat, - formatDepthStencil: TextureFormat, + pub const SwapChain = extern struct { + nwh: ?*anyopaque, + ndt: ?*anyopaque, width: u32, height: u32, - reset: u32, + flags: u32, + formatColor: TextureFormat, + formatDepthStencil: TextureFormat, + depth: TextureHandle, numBackBuffers: u8, maxFrameLatency: u8, - debugTextScale: u8, }; pub const Init = extern struct { @@ -1670,7 +1703,8 @@ pub const Init = extern struct { fallback: bool, videoDecode: bool, platformData: PlatformData, - resolution: Resolution, + swapChain: SwapChain, + reset: u32, limits: Limits, callback: ?*anyopaque, allocator: ?*anyopaque, @@ -2588,14 +2622,12 @@ extern fn bgfx_shutdown() void; /// @attention This call doesn’t change the window size, it just resizes /// the back-buffer. Your windowing code controls the window size. /// -/// Back-buffer width. -/// Back-buffer height. -/// See: `BGFX_RESET_*` for more info. - `BGFX_RESET_NONE` - No reset flags. - `BGFX_RESET_FULLSCREEN` - Not supported yet. - `BGFX_RESET_MSAA_X[2/4/8/16]` - Enable 2, 4, 8 or 16 x MSAA. - `BGFX_RESET_VSYNC` - Enable V-Sync. - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. - `BGFX_RESET_CAPTURE` - Begin screen capture. - `BGFX_RESET_FLUSH_AFTER_RENDER` - Flush rendering after submitting to GPU. - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip occurs. Default behaviour is that flip occurs before rendering new frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. - `BGFX_RESET_SRGB_BACKBUFFER` - Enable sRGB back-buffer. -/// Texture format. See: `TextureFormat::Enum`. -pub inline fn reset(_width: u32, _height: u32, _flags: u32, _format: TextureFormat) void { - return bgfx_reset(_width, _height, _flags, _format); +/// See: `BGFX_RESET_*` for more info. - `BGFX_RESET_NONE` - No reset flags. - `BGFX_RESET_VSYNC` - Enable V-Sync. - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. - `BGFX_RESET_CAPTURE` - Begin screen capture. - `BGFX_RESET_FLUSH_AFTER_RENDER` - Flush rendering after submitting to GPU. - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip occurs. Default behaviour is that flip occurs before rendering new frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. Per-surface settings are not here. `BGFX_SWAP_CHAIN_*` flags belong on `SwapChain::flags`, and are ignored if passed here. +/// Main window swap chain. When `NULL` the main window is left untouched and only the device and frame globals above are applied, which is what an application driving its own swap chains wants. Otherwise the main window takes on this description: resize it, change its format, or change its per-surface flags. Fields left neutral keep their current value, and `nwh`/`ndt` are ignored -- main's are bgfx's own. Must be `NULL` when `bgfx::init` created no main window. +pub inline fn reset(_flags: u32, _swapChain: [*c]const SwapChain) void { + return bgfx_reset(_flags, _swapChain); } -extern fn bgfx_reset(_width: u32, _height: u32, _flags: u32, _format: TextureFormat) void; +extern fn bgfx_reset(_flags: u32, _swapChain: [*c]const SwapChain) void; /// Advance to next frame. This is the main frame-advancement call on the /// API thread (the thread from which `bgfx::init` was called). @@ -2707,10 +2739,12 @@ extern fn bgfx_make_ref_release(_data: ?*const anyopaque, _size: u32, _releaseFn /// Set debug flags. /// Available flags: - `BGFX_DEBUG_IFH` - Infinitely fast hardware. When this flag is set all rendering calls will be skipped. This is useful when profiling to quickly assess potential bottlenecks between CPU and GPU. - `BGFX_DEBUG_PROFILER` - Enable profiler. - `BGFX_DEBUG_STATS` - Display internal statistics. - `BGFX_DEBUG_TEXT` - Display debug text. - `BGFX_DEBUG_WIREFRAME` - Wireframe rendering. All rendering primitives will be rendered as lines. -pub inline fn setDebug(_debug: u32) void { - return bgfx_set_debug(_debug); +/// Frame buffer the debug text and statistics are drawn on. Invalid handle selects the window bgfx was initialized with. +/// Debug text scale factor. 0 is the same as 1. +pub inline fn setDebug(_debug: u32, _handle: FrameBufferHandle, _scale: u8) void { + return bgfx_set_debug(_debug, _handle, _scale); } -extern fn bgfx_set_debug(_debug: u32) void; +extern fn bgfx_set_debug(_debug: u32, _handle: FrameBufferHandle, _scale: u8) void; /// Clear internal debug text buffer. /// Background color. @@ -3298,22 +3332,33 @@ pub inline fn createFrameBufferFromAttachment(_num: u8, _attachment: [*c]const A } extern fn bgfx_create_frame_buffer_from_attachment(_num: u8, _attachment: [*c]const Attachment, _destroyTexture: bool) FrameBufferHandle; -/// Create frame buffer for multiple window rendering. +/// Create a frame buffer for a window, from a full swap chain description. /// /// @remarks /// Frame buffer cannot be used for sampling. /// /// @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. /// -/// OS' target native window handle. -/// Window back buffer width. -/// Window back buffer height. -/// Window back buffer color format. -/// Window back buffer depth format. -pub inline fn createFrameBufferFromNwh(_nwh: ?*anyopaque, _width: u16, _height: u16, _format: TextureFormat, _depthFormat: TextureFormat) FrameBufferHandle { - return bgfx_create_frame_buffer_from_nwh(_nwh, _width, _height, _format, _depthFormat); +/// Swap chain description. See: `bgfx::SwapChain`. +pub inline fn createFrameBufferFromSwapChain(_desc: [*c]const SwapChain) FrameBufferHandle { + return bgfx_create_frame_buffer_from_swap_chain(_desc); } -extern fn bgfx_create_frame_buffer_from_nwh(_nwh: ?*anyopaque, _width: u16, _height: u16, _format: TextureFormat, _depthFormat: TextureFormat) FrameBufferHandle; +extern fn bgfx_create_frame_buffer_from_swap_chain(_desc: [*c]const SwapChain) FrameBufferHandle; + +/// Change a swap chain's size, format or per-surface flags, in place. +/// +/// The frame buffer handle stays valid, so nothing that refers to it has to be +/// rebuilt. Pass `BGFX_INVALID_HANDLE` to address the window bgfx was +/// initialized with. +/// +/// @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. +/// +/// Window frame buffer handle. The window bgfx was initialized with is not addressed here; it is `bgfx::reset`'s swap chain. +/// Swap chain description. See: `bgfx::SwapChain`. +pub inline fn updateSwapChain(_handle: FrameBufferHandle, _desc: [*c]const SwapChain) void { + return bgfx_update_swap_chain(_handle, _desc); +} +extern fn bgfx_update_swap_chain(_handle: FrameBufferHandle, _desc: [*c]const SwapChain) void; /// Set frame buffer debug name. /// Frame buffer handle. @@ -4152,16 +4197,6 @@ pub inline fn renderFrame(_msecs: i32) RenderFrame { } extern fn bgfx_render_frame(_msecs: i32) RenderFrame; -/// Set platform data. -/// -/// @warning Must be called before `bgfx::init`. -/// -/// Platform data. -pub inline fn setPlatformData(_data: [*c]const PlatformData) void { - return bgfx_set_platform_data(_data); -} -extern fn bgfx_set_platform_data(_data: [*c]const PlatformData) void; - /// Get internal data for interop. /// /// @attention It's expected you understand some bgfx internals before you @@ -4174,44 +4209,6 @@ pub inline fn getInternalData() [*c]const InternalData { } extern fn bgfx_get_internal_data() [*c]const InternalData; -/// Override internal texture with externally created texture. Previously -/// created internal texture will released. -/// -/// @attention It's expected you understand some bgfx internals before you -/// use this call. -/// -/// @warning Must be called only on render thread. -/// -/// Texture handle. -/// Native API pointer to texture. -/// Layer index for texture arrays (only implemented for D3D11). -pub inline fn overrideInternalTexturePtr(_handle: TextureHandle, _ptr: usize, _layerIndex: u16) usize { - return bgfx_override_internal_texture_ptr(_handle, _ptr, _layerIndex); -} -extern fn bgfx_override_internal_texture_ptr(_handle: TextureHandle, _ptr: usize, _layerIndex: u16) usize; - -/// Override internal texture by creating new texture. Previously created -/// internal texture will released. -/// -/// @attention It's expected you understand some bgfx internals before you -/// use this call. -/// -/// @returns Native API pointer to texture. If result is 0, texture is not created yet from the -/// main thread. -/// -/// @warning Must be called only on render thread. -/// -/// Texture handle. -/// Width. -/// Height. -/// Number of mip-maps. -/// Texture format. See: `TextureFormat::Enum`. -/// Texture creation (see `BGFX_TEXTURE_*`.), and sampler (see `BGFX_SAMPLER_*`) flags. Default texture sampling mode is linear, and wrap mode is repeat. - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap mode. - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic sampling. -pub inline fn overrideInternalTexture(_handle: TextureHandle, _width: u16, _height: u16, _numMips: u8, _format: TextureFormat, _flags: u64) usize { - return bgfx_override_internal_texture(_handle, _width, _height, _numMips, _format, _flags); -} -extern fn bgfx_override_internal_texture(_handle: TextureHandle, _width: u16, _height: u16, _numMips: u8, _format: TextureFormat, _flags: u64) usize; - /// Sets a debug marker. This allows you to group graphics calls together for easy browsing in /// graphics debugging tools. /// Marker name. diff --git a/docs/bgfx.rst b/docs/bgfx.rst index 232f64dff..657b6bf82 100644 --- a/docs/bgfx.rst +++ b/docs/bgfx.rst @@ -30,9 +30,6 @@ Initialization and Shutdown .. doxygendefine:: BGFX_PCI_ID_MICROSOFT .. doxygendefine:: BGFX_PCI_ID_ARM -.. doxygenstruct:: bgfx::Resolution - :members: - .. doxygenstruct:: bgfx::Init :members: @@ -63,6 +60,25 @@ Reset flags control back-buffer resolution, MSAA, vsync, and other global render .. doxygenfunction:: bgfx::reset +Swap Chain +********** + +Swap chain flags control properties of a single presentation surface. They are numerically +identical to their ``BGFX_RESET_*`` counterparts, so main's flags round-trip losslessly. + +.. doxygendefine:: BGFX_SWAP_CHAIN_NONE +.. doxygendefine:: BGFX_SWAP_CHAIN_FULLSCREEN +.. doxygendefine:: BGFX_SWAP_CHAIN_SRGB_BACKBUFFER +.. doxygendefine:: BGFX_SWAP_CHAIN_HDR10 +.. doxygendefine:: BGFX_SWAP_CHAIN_HIDPI +.. doxygendefine:: BGFX_SWAP_CHAIN_TRANSPARENT_BACKBUFFER + +.. doxygenstruct:: bgfx::SwapChain + :members: + +.. doxygenfunction:: bgfx::createFrameBuffer(const SwapChain& _desc) +.. doxygenfunction:: bgfx::updateSwapChain + Frame ***** @@ -200,10 +216,7 @@ It is only necessary to use these APIs in conjunction with creating windows. :members: .. doxygenfunction:: bgfx::renderFrame -.. doxygenfunction:: bgfx::setPlatformData .. doxygenfunction:: bgfx::getInternalData -.. doxygenfunction:: bgfx::overrideInternal(TextureHandle _handle, uintptr_t _ptr, uint16_t _layerIndex = 0) -.. doxygenfunction:: bgfx::overrideInternal(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint64_t _flags = BGFX_TEXTURE_NONE | BGFX_SAMPLER_NONE) Miscellaneous ~~~~~~~~~~~~~ @@ -656,7 +669,6 @@ Frame Buffers .. doxygenfunction:: bgfx::createFrameBuffer(BackbufferRatio::Enum _ratio, TextureFormat::Enum _format, uint64_t _textureFlags = BGFX_SAMPLER_U_CLAMP|BGFX_SAMPLER_V_CLAMP) .. doxygenfunction:: bgfx::createFrameBuffer(uint8_t _num, const TextureHandle* _handles, bool _destroyTexture) .. doxygenfunction:: bgfx::createFrameBuffer(uint8_t _num, const Attachment* _attachment, bool _destroyTexture) -.. doxygenfunction:: bgfx::createFrameBuffer(void* _nwh, uint16_t _width, uint16_t _height, TextureFormat::Enum _format = TextureFormat::Count, TextureFormat::Enum _depthFormat = TextureFormat::Count) .. doxygenfunction:: bgfx::setName(FrameBufferHandle _handle, const char* _name, int32_t _len = INT32_MAX) .. doxygenfunction:: bgfx::getTexture .. doxygenfunction:: bgfx::destroy(FrameBufferHandle _handle) diff --git a/docs/internals.rst b/docs/internals.rst index 5395adf88..10b90c42d 100644 --- a/docs/internals.rst +++ b/docs/internals.rst @@ -256,9 +256,9 @@ Sort key Swap chain ^^^^^^^^^^ -``BGFX_CONFIG_MAX_BACK_BUFFERS`` - Maximum number of back buffers for the swap chain. Default is 4. The actual number used is specified via ``bgfx::Resolution::numBackBuffers``. +``BGFX_CONFIG_MAX_BACK_BUFFERS`` - Maximum number of back buffers for the swap chain. Default is 4. The actual number used is specified via ``bgfx::SwapChain::numBackBuffers``. -``BGFX_CONFIG_MAX_FRAME_LATENCY`` - Maximum frame latency (number of frames that can be queued ahead). Default is 3. The actual value is specified via ``bgfx::Resolution::maxFrameLatency``. +``BGFX_CONFIG_MAX_FRAME_LATENCY`` - Maximum frame latency (number of frames that can be queued ahead). Default is 3. The actual value is specified via ``bgfx::SwapChain::maxFrameLatency``. Debugging and profiling ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/examples/00-helloworld/helloworld.cpp b/examples/00-helloworld/helloworld.cpp index a6d8799a0..54c44d414 100644 --- a/examples/00-helloworld/helloworld.cpp +++ b/examples/00-helloworld/helloworld.cpp @@ -31,12 +31,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/01-cubes/cubes.cpp b/examples/01-cubes/cubes.cpp index d0d521f46..30f165f7e 100644 --- a/examples/01-cubes/cubes.cpp +++ b/examples/01-cubes/cubes.cpp @@ -147,12 +147,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/02-metaballs/metaballs.cpp b/examples/02-metaballs/metaballs.cpp index e6667cc14..1f3c075a2 100644 --- a/examples/02-metaballs/metaballs.cpp +++ b/examples/02-metaballs/metaballs.cpp @@ -506,12 +506,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/03-raymarch/raymarch.cpp b/examples/03-raymarch/raymarch.cpp index 49aa90bfb..96c897247 100644 --- a/examples/03-raymarch/raymarch.cpp +++ b/examples/03-raymarch/raymarch.cpp @@ -119,12 +119,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/04-mesh/mesh.cpp b/examples/04-mesh/mesh.cpp index b21dcbaeb..6d2bc713d 100644 --- a/examples/04-mesh/mesh.cpp +++ b/examples/04-mesh/mesh.cpp @@ -30,12 +30,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/05-instancing/instancing.cpp b/examples/05-instancing/instancing.cpp index 649b2e1e2..b5b908202 100644 --- a/examples/05-instancing/instancing.cpp +++ b/examples/05-instancing/instancing.cpp @@ -82,12 +82,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/06-bump/bump.cpp b/examples/06-bump/bump.cpp index f5644ae82..f1987f299 100644 --- a/examples/06-bump/bump.cpp +++ b/examples/06-bump/bump.cpp @@ -102,12 +102,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/07-callback/callback.cpp b/examples/07-callback/callback.cpp index a0d7d6e2e..675908d00 100644 --- a/examples/07-callback/callback.cpp +++ b/examples/07-callback/callback.cpp @@ -364,12 +364,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; init.callback = &m_callback; // custom callback handler init.allocator = &m_allocator; // custom allocator bgfx::init(init); diff --git a/examples/08-update/update.cpp b/examples/08-update/update.cpp index 6952bede2..d0b9b9e3b 100644 --- a/examples/08-update/update.cpp +++ b/examples/08-update/update.cpp @@ -256,12 +256,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/09-hdr/hdr.cpp b/examples/09-hdr/hdr.cpp index 58d483536..efabafb4e 100644 --- a/examples/09-hdr/hdr.cpp +++ b/examples/09-hdr/hdr.cpp @@ -153,12 +153,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable m_debug text. diff --git a/examples/10-font/font.cpp b/examples/10-font/font.cpp index 3faf78d20..bc80bc40d 100644 --- a/examples/10-font/font.cpp +++ b/examples/10-font/font.cpp @@ -71,12 +71,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/11-fontsdf/fontsdf.cpp b/examples/11-fontsdf/fontsdf.cpp index d79e3087d..60186b376 100644 --- a/examples/11-fontsdf/fontsdf.cpp +++ b/examples/11-fontsdf/fontsdf.cpp @@ -54,12 +54,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/12-lod/lod.cpp b/examples/12-lod/lod.cpp index a3aa6c038..1f7b78cf8 100644 --- a/examples/12-lod/lod.cpp +++ b/examples/12-lod/lod.cpp @@ -46,12 +46,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/13-stencil/stencil.cpp b/examples/13-stencil/stencil.cpp index f4604b876..db48c17c8 100644 --- a/examples/13-stencil/stencil.cpp +++ b/examples/13-stencil/stencil.cpp @@ -813,12 +813,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_viewState.m_width; - init.resolution.height = m_viewState.m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_viewState.m_width; + init.swapChain.height = m_viewState.m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/14-shadowvolumes/shadowvolumes.cpp b/examples/14-shadowvolumes/shadowvolumes.cpp index 55f398aa6..cd172d90a 100644 --- a/examples/14-shadowvolumes/shadowvolumes.cpp +++ b/examples/14-shadowvolumes/shadowvolumes.cpp @@ -1716,12 +1716,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_viewState.m_width; - init.resolution.height = m_viewState.m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_viewState.m_width; + init.swapChain.height = m_viewState.m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/15-shadowmaps-simple/shadowmaps_simple.cpp b/examples/15-shadowmaps-simple/shadowmaps_simple.cpp index 2ea0173f4..5031010ad 100644 --- a/examples/15-shadowmaps-simple/shadowmaps_simple.cpp +++ b/examples/15-shadowmaps-simple/shadowmaps_simple.cpp @@ -78,12 +78,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/16-shadowmaps/shadowmaps.cpp b/examples/16-shadowmaps/shadowmaps.cpp index 7af9803cc..390c9fc56 100644 --- a/examples/16-shadowmaps/shadowmaps.cpp +++ b/examples/16-shadowmaps/shadowmaps.cpp @@ -1151,12 +1151,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_viewState.m_width; - init.resolution.height = m_viewState.m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_viewState.m_width; + init.swapChain.height = m_viewState.m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/17-drawstress/drawstress.cpp b/examples/17-drawstress/drawstress.cpp index 9a3e2f3de..87e4c100c 100644 --- a/examples/17-drawstress/drawstress.cpp +++ b/examples/17-drawstress/drawstress.cpp @@ -220,12 +220,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; init.limits.numDrawCalls = UINT32_MAX; // Prealloc to maximum draw calls. init.limits.numDrawCallPeakFrames = 0; // Do not adjust in runtime. bgfx::init(init); diff --git a/examples/18-ibl/ibl.cpp b/examples/18-ibl/ibl.cpp index 90ee74b23..63cbb5ae1 100644 --- a/examples/18-ibl/ibl.cpp +++ b/examples/18-ibl/ibl.cpp @@ -418,12 +418,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/19-oit/oit.cpp b/examples/19-oit/oit.cpp index 3f34661d2..4c720d8a0 100644 --- a/examples/19-oit/oit.cpp +++ b/examples/19-oit/oit.cpp @@ -169,12 +169,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/20-nanovg/nanovg.cpp b/examples/20-nanovg/nanovg.cpp index fe8219ea5..f23a97534 100644 --- a/examples/20-nanovg/nanovg.cpp +++ b/examples/20-nanovg/nanovg.cpp @@ -1402,12 +1402,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/21-deferred/deferred.cpp b/examples/21-deferred/deferred.cpp index 7e84f6e9d..225447d59 100644 --- a/examples/21-deferred/deferred.cpp +++ b/examples/21-deferred/deferred.cpp @@ -207,12 +207,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable m_debug text. diff --git a/examples/22-windows/windows.cpp b/examples/22-windows/windows.cpp index 657a65c2b..6cb698f24 100644 --- a/examples/22-windows/windows.cpp +++ b/examples/22-windows/windows.cpp @@ -86,12 +86,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); const bgfx::Caps* caps = bgfx::getCaps(); @@ -199,27 +199,14 @@ public: || (win.m_width != m_state.m_width || win.m_height != m_state.m_height) ) { - // When window changes size or native window handle changed - // frame buffer must be recreated. - if (bgfx::isValid(m_fbh[viewId]) ) + if (win.m_nwh != m_state.m_nwh + && bgfx::isValid(m_fbh[viewId]) ) { bgfx::destroy(m_fbh[viewId]); m_fbh[viewId].idx = bgfx::kInvalidHandle; - } - // Before we reattach a SwapChain to the window - // we must actually free up the previous one. - // The DestroyFrameBuffer command goes in the - // cmdPost CommandBuffer, which happens after - // the frame. The CreateFrameBuffer command goes - // int the cmdPre CommandBuffer, which happens - // at the beginning of the frame. Without this - // bgfx::frame() call, the creation would happen - // before it's destroyed, which would cause - // the platform window to have two SwapChains - // associated with it. - // Ideally, we have an operation of ResizeFrameBuffer. - bgfx::frame(); + bgfx::frame(); + } win.m_nwh = m_state.m_nwh; win.m_width = m_state.m_width; @@ -227,7 +214,19 @@ public: if (NULL != win.m_nwh) { - m_fbh[viewId] = bgfx::createFrameBuffer(win.m_nwh, uint16_t(win.m_width), uint16_t(win.m_height) ); + bgfx::SwapChain swapChain; + swapChain.nwh = win.m_nwh; + swapChain.width = win.m_width; + swapChain.height = win.m_height; + + if (bgfx::isValid(m_fbh[viewId]) ) + { + bgfx::updateSwapChain(m_fbh[viewId], swapChain); + } + else + { + m_fbh[viewId] = bgfx::createFrameBuffer(swapChain); + } } else { diff --git a/examples/23-vectordisplay/main.cpp b/examples/23-vectordisplay/main.cpp index 5b2903d31..561355df6 100644 --- a/examples/23-vectordisplay/main.cpp +++ b/examples/23-vectordisplay/main.cpp @@ -53,11 +53,11 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); m_vd.init(bgfx::getCaps()->originBottomLeft); diff --git a/examples/24-nbody/nbody.cpp b/examples/24-nbody/nbody.cpp index 61ff0370c..918e5131f 100644 --- a/examples/24-nbody/nbody.cpp +++ b/examples/24-nbody/nbody.cpp @@ -130,12 +130,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/25-c99/helloworld.c b/examples/25-c99/helloworld.c index 072e484fc..72e2cf579 100644 --- a/examples/25-c99/helloworld.c +++ b/examples/25-c99/helloworld.c @@ -28,15 +28,18 @@ int32_t _main_(int32_t _argc, char** _argv) bgfx_init_t init; bgfx_init_ctor(&init); - init.platformData.nwh = entry_get_default_native_window_handle(); - init.platformData.ndt = entry_get_native_display_handle(); + init.swapChain.width = width; + init.swapChain.height = height; + + init.swapChain.nwh = entry_get_default_native_window_handle(); + init.swapChain.ndt = entry_get_native_display_handle(); init.platformData.type = entry_get_native_window_handle_type(); bgfx_init(&init); - bgfx_reset(width, height, reset, init.resolution.formatColor); + bgfx_reset(reset, &init.swapChain); // Enable debug text. - bgfx_set_debug(debug); + bgfx_set_debug(debug, (bgfx_frame_buffer_handle_t)BGFX_INVALID_HANDLE, 0); bgfx_set_view_clear(0 , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH diff --git a/examples/26-occlusion/occlusion.cpp b/examples/26-occlusion/occlusion.cpp index 0cbfe4c6d..f3a73bcf9 100644 --- a/examples/26-occlusion/occlusion.cpp +++ b/examples/26-occlusion/occlusion.cpp @@ -82,12 +82,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/27-terrain/terrain.cpp b/examples/27-terrain/terrain.cpp index 64700854f..a032caf85 100644 --- a/examples/27-terrain/terrain.cpp +++ b/examples/27-terrain/terrain.cpp @@ -78,12 +78,12 @@ ExampleTerrain(const char* _name, const char* _description, const char* _url) bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable m_debug text. diff --git a/examples/28-wireframe/wireframe.cpp b/examples/28-wireframe/wireframe.cpp index e78da8a83..2e2e429ab 100644 --- a/examples/28-wireframe/wireframe.cpp +++ b/examples/28-wireframe/wireframe.cpp @@ -293,12 +293,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable m_debug text. diff --git a/examples/29-debugdraw/debugdraw.cpp b/examples/29-debugdraw/debugdraw.cpp index 58d085359..c81b001a3 100644 --- a/examples/29-debugdraw/debugdraw.cpp +++ b/examples/29-debugdraw/debugdraw.cpp @@ -776,12 +776,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable m_debug text. diff --git a/examples/30-picking/picking.cpp b/examples/30-picking/picking.cpp index 085b81d59..14458c71a 100644 --- a/examples/30-picking/picking.cpp +++ b/examples/30-picking/picking.cpp @@ -38,12 +38,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/31-rsm/reflectiveshadowmap.cpp b/examples/31-rsm/reflectiveshadowmap.cpp index c493438da..bf7b509af 100644 --- a/examples/31-rsm/reflectiveshadowmap.cpp +++ b/examples/31-rsm/reflectiveshadowmap.cpp @@ -208,12 +208,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/32-particles/particles.cpp b/examples/32-particles/particles.cpp index 139e5586f..f4c4303ff 100644 --- a/examples/32-particles/particles.cpp +++ b/examples/32-particles/particles.cpp @@ -246,12 +246,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable m_debug text. diff --git a/examples/33-pom/pom.cpp b/examples/33-pom/pom.cpp index 69ceae1f6..e115c3c44 100644 --- a/examples/33-pom/pom.cpp +++ b/examples/33-pom/pom.cpp @@ -114,12 +114,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/34-mvs/mvs.cpp b/examples/34-mvs/mvs.cpp index 455e4af25..cdc54d611 100644 --- a/examples/34-mvs/mvs.cpp +++ b/examples/34-mvs/mvs.cpp @@ -124,12 +124,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/35-dynamic/dynamic.cpp b/examples/35-dynamic/dynamic.cpp index e1c597108..fc0522040 100644 --- a/examples/35-dynamic/dynamic.cpp +++ b/examples/35-dynamic/dynamic.cpp @@ -102,12 +102,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/36-sky/sky.cpp b/examples/36-sky/sky.cpp index 3b22b8a82..1007ecb2c 100644 --- a/examples/36-sky/sky.cpp +++ b/examples/36-sky/sky.cpp @@ -418,12 +418,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable m_debug text. diff --git a/examples/37-gpudrivenrendering/gpudrivenrendering.cpp b/examples/37-gpudrivenrendering/gpudrivenrendering.cpp index c1cd28d8c..7c3eba917 100644 --- a/examples/37-gpudrivenrendering/gpudrivenrendering.cpp +++ b/examples/37-gpudrivenrendering/gpudrivenrendering.cpp @@ -328,12 +328,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/38-bloom/bloom.cpp b/examples/38-bloom/bloom.cpp index 40f48b001..b5dc26921 100644 --- a/examples/38-bloom/bloom.cpp +++ b/examples/38-bloom/bloom.cpp @@ -194,12 +194,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable m_debug text. diff --git a/examples/39-assao/assao.cpp b/examples/39-assao/assao.cpp index fba5fdbb9..4eb0ced73 100644 --- a/examples/39-assao/assao.cpp +++ b/examples/39-assao/assao.cpp @@ -266,12 +266,12 @@ namespace bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/40-svt/svt.cpp b/examples/40-svt/svt.cpp index 62d7357b3..eff21553e 100644 --- a/examples/40-svt/svt.cpp +++ b/examples/40-svt/svt.cpp @@ -80,12 +80,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable m_debug text. diff --git a/examples/41-tess/tess.cpp b/examples/41-tess/tess.cpp index b940a9226..af849451d 100644 --- a/examples/41-tess/tess.cpp +++ b/examples/41-tess/tess.cpp @@ -337,12 +337,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); m_dmap = { "textures/dmap.png", 0.45f }; diff --git a/examples/42-bunnylod/bunnylod.cpp b/examples/42-bunnylod/bunnylod.cpp index 4b1187985..94334a35e 100644 --- a/examples/42-bunnylod/bunnylod.cpp +++ b/examples/42-bunnylod/bunnylod.cpp @@ -263,12 +263,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/43-denoise/denoise.cpp b/examples/43-denoise/denoise.cpp index 2f1e77271..09ebc18ad 100644 --- a/examples/43-denoise/denoise.cpp +++ b/examples/43-denoise/denoise.cpp @@ -248,12 +248,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/44-sss/screen_space_shadows.cpp b/examples/44-sss/screen_space_shadows.cpp index 9d701f587..2930a4124 100644 --- a/examples/44-sss/screen_space_shadows.cpp +++ b/examples/44-sss/screen_space_shadows.cpp @@ -260,12 +260,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/45-bokeh/bokeh.cpp b/examples/45-bokeh/bokeh.cpp index 708f0e1e6..f04c4f337 100644 --- a/examples/45-bokeh/bokeh.cpp +++ b/examples/45-bokeh/bokeh.cpp @@ -242,12 +242,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/46-fsr/app.cpp b/examples/46-fsr/app.cpp index d166121b9..61a696c8a 100644 --- a/examples/46-fsr/app.cpp +++ b/examples/46-fsr/app.cpp @@ -371,11 +371,11 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); - init.resolution.width = m_state.m_width; - init.resolution.height = m_state.m_height; - init.resolution.reset = m_state.m_reset; + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); + init.swapChain.width = m_state.m_width; + init.swapChain.height = m_state.m_height; + init.reset = m_state.m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/47-pixelformats/pixelformats.cpp b/examples/47-pixelformats/pixelformats.cpp index a9c1eba8c..92afe7484 100644 --- a/examples/47-pixelformats/pixelformats.cpp +++ b/examples/47-pixelformats/pixelformats.cpp @@ -436,12 +436,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/48-drawindirect/drawindirect.cpp b/examples/48-drawindirect/drawindirect.cpp index 47a4a504e..216350791 100644 --- a/examples/48-drawindirect/drawindirect.cpp +++ b/examples/48-drawindirect/drawindirect.cpp @@ -146,12 +146,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/49-hextile/hextile.cpp b/examples/49-hextile/hextile.cpp index 01518eff6..52a0257d5 100644 --- a/examples/49-hextile/hextile.cpp +++ b/examples/49-hextile/hextile.cpp @@ -83,12 +83,12 @@ namespace bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable m_debug text. diff --git a/examples/50-headless/headless.cpp b/examples/50-headless/headless.cpp index 1733e61b0..0bf8a10d6 100644 --- a/examples/50-headless/headless.cpp +++ b/examples/50-headless/headless.cpp @@ -71,8 +71,8 @@ int _main_(int _argc, char** _argv) bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.resolution.width = 0; - init.resolution.height = 0; + init.swapChain.width = 0; + init.swapChain.height = 0; if (!bgfx::init(init) ) { diff --git a/examples/51-gpufont/gpufont.cpp b/examples/51-gpufont/gpufont.cpp index 52883f0f7..77466a284 100644 --- a/examples/51-gpufont/gpufont.cpp +++ b/examples/51-gpufont/gpufont.cpp @@ -996,12 +996,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); bgfx::setDebug(m_debug); diff --git a/examples/52-layered/layered.cpp b/examples/52-layered/layered.cpp index cfdc83e6e..16af94ff0 100644 --- a/examples/52-layered/layered.cpp +++ b/examples/52-layered/layered.cpp @@ -159,12 +159,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); // Enable debug text. diff --git a/examples/53-sky2/sky2.cpp b/examples/53-sky2/sky2.cpp index e9c32bcc0..a3b5634dc 100644 --- a/examples/53-sky2/sky2.cpp +++ b/examples/53-sky2/sky2.cpp @@ -78,12 +78,12 @@ public: bgfx::Init init; init.type = args.m_type; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); init.platformData.type = entry::getNativeWindowHandleType(); - init.resolution.width = m_width; - init.resolution.height = m_height; - init.resolution.reset = m_reset; + init.swapChain.width = m_width; + init.swapChain.height = m_height; + init.reset = m_reset; bgfx::init(init); bgfx::setDebug(m_debug); diff --git a/examples/common/entry/entry.cpp b/examples/common/entry/entry.cpp index 30e876f38..bcf07c54b 100644 --- a/examples/common/entry/entry.cpp +++ b/examples/common/entry/entry.cpp @@ -29,6 +29,25 @@ namespace entry static uint32_t s_height = ENTRY_DEFAULT_HEIGHT; static bool s_exit = false; + static void resetMainWindow(uint32_t _width, uint32_t _height, uint32_t _reset) + { + constexpr uint32_t kSwapChainFlags = 0 + | BGFX_SWAP_CHAIN_FULLSCREEN_MASK + | BGFX_SWAP_CHAIN_MSAA_MASK + | BGFX_SWAP_CHAIN_SRGB_BACKBUFFER + | BGFX_SWAP_CHAIN_HDR10 + | BGFX_SWAP_CHAIN_HIDPI + | BGFX_SWAP_CHAIN_TRANSPARENT_BACKBUFFER + ; + + bgfx::SwapChain swapChain; + swapChain.width = _width; + swapChain.height = _height; + swapChain.flags = _reset & kSwapChainFlags; + + bgfx::reset(_reset & ~kSwapChainFlags, &swapChain); + } + static bx::FileReaderI* s_fileReader = NULL; static bx::FileWriterI* s_fileWriter = NULL; @@ -843,7 +862,7 @@ restart: { _reset = s_reset; BX_TRACE("bgfx::reset(%d, %d, 0x%x)", _width, _height, _reset); - bgfx::reset(_width, _height, _reset); + resetMainWindow(_width, _height, _reset); inputSetMouseResolution(uint16_t(_width), uint16_t(_height) ); } @@ -1023,7 +1042,7 @@ restart: { _reset = s_reset; BX_TRACE("bgfx::reset(%d, %d, 0x%x)", s_window[0].m_width, s_window[0].m_height, _reset); - bgfx::reset(s_window[0].m_width, s_window[0].m_height, _reset); + resetMainWindow(s_window[0].m_width, s_window[0].m_height, _reset); inputSetMouseResolution(uint16_t(s_window[0].m_width), uint16_t(s_window[0].m_height) ); } diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index 8e077197a..9e4db758e 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -326,6 +326,12 @@ namespace bgfx /// Backbuffer ratio enum. /// + /// The ratio is always relative to the window bgfx was initialized with, and is + /// re-resolved by `bgfx::reset`. It is not relative to whichever window a texture + /// happens to be rendered to, so on a second window a ratio texture is not + /// meaningfully sized. For that reason a ratio texture cannot be used as + /// `SwapChain::depth`. + /// /// @attention C99's equivalent binding is `bgfx_backbuffer_ratio_t`. /// struct BackbufferRatio @@ -333,12 +339,12 @@ namespace bgfx /// Backbuffer ratios: enum Enum { - Equal, //!< Equal to backbuffer. - Half, //!< One half size of backbuffer. - Quarter, //!< One quarter size of backbuffer. - Eighth, //!< One eighth size of backbuffer. - Sixteenth, //!< One sixteenth size of backbuffer. - Double, //!< Double size of backbuffer. + Equal, //!< Equal to the main window's backbuffer. + Half, //!< One half size of the main window's backbuffer. + Quarter, //!< One quarter size of the main window's backbuffer. + Eighth, //!< One eighth size of the main window's backbuffer. + Sixteenth, //!< One sixteenth size of the main window's backbuffer. + Double, //!< Double size of the main window's backbuffer. Count }; @@ -700,35 +706,36 @@ namespace bgfx { PlatformData(); - void* ndt; //!< Native display type (*nix specific). - void* nwh; //!< Native window handle. If `NULL`, bgfx will create a headless - /// context/device, provided the rendering API supports it. void* context; //!< GL context, D3D device, or Vulkan device. If `NULL`, bgfx /// will create context/device. void* queue; //!< D3D12 Queue. If `NULL` bgfx will create queue. - void* backBuffer; //!< GL back-buffer, or D3D render target view. If `NULL` bgfx will - /// create back-buffer color surface. - void* backBufferDS; //!< Backbuffer depth/stencil. If `NULL`, bgfx will create a back-buffer - /// depth/stencil surface. NativeWindowHandleType::Enum type; //!< Handle type. Needed for platforms having more than one option. }; - /// Backbuffer resolution and reset parameters. + /// Swap chain description. /// - /// @attention C99's equivalent binding is `bgfx_resolution_t`. + /// @attention C99's equivalent binding is `bgfx_swap_chain_t`. /// - struct Resolution + struct SwapChain { - Resolution(); + SwapChain(); - TextureFormat::Enum formatColor; //!< Backbuffer color format. - TextureFormat::Enum formatDepthStencil; //!< Backbuffer depth/stencil format. - uint32_t width; //!< Backbuffer width. - uint32_t height; //!< Backbuffer height. - uint32_t reset; //!< Reset parameters. + void* nwh; //!< Native window handle. If `NULL`, bgfx will create a headless + /// context/device, provided the rendering API supports it. + void* ndt; //!< Native display type (*nix specific). A window that leaves this + /// `NULL` uses the one the main window was initialized with. + uint32_t width; //!< Swap chain width. + uint32_t height; //!< Swap chain height. + uint32_t flags; //!< See: `BGFX_SWAP_CHAIN_*`. + TextureFormat::Enum formatColor; //!< Color format. + TextureFormat::Enum formatDepthStencil; //!< Depth/stencil format, or `TextureFormat::Count` for no depth. Ignored + /// when `depth` is valid. + TextureHandle depth; //!< Depth attachment. Must be created with `BGFX_TEXTURE_RT`, and match the + /// swap chain width, height and sample count. When invalid, bgfx creates and + /// owns a depth surface per `formatDepthStencil`. A texture supplied here is + /// never destroyed by bgfx, and may be shared by several same-size swap chains. uint8_t numBackBuffers; //!< Number of back buffers. uint8_t maxFrameLatency; //!< Maximum frame latency. - uint8_t debugTextScale; //!< Scale factor for debug text. }; /// Initialization parameters used by `bgfx::init`. @@ -786,7 +793,11 @@ namespace bgfx bool fallback; //!< Enable fallback to next available renderer. bool videoDecode; //!< Enable video decoding. PlatformData platformData; //!< Platform data. - Resolution resolution; //!< Backbuffer resolution and reset parameters. See: `bgfx::Resolution`. + SwapChain swapChain; //!< Swap chain for the window bgfx creates its device on. + /// See: `bgfx::SwapChain`. + uint32_t reset; //!< Device and frame global settings. Anything that is a + /// property of one surface belongs in `swapChain` instead. + /// See: `BGFX_RESET_*`. Limits limits; //!< Configurable runtime limits parameters. CallbackI* callback; //!< Provide application specific callback interface. /// See: `bgfx::CallbackI` @@ -2469,12 +2480,8 @@ namespace bgfx /// Reset graphic settings and back-buffer size. /// - /// @param[in] _width Back-buffer width. - /// @param[in] _height Back-buffer height. /// @param[in] _flags See: `BGFX_RESET_*` for more info. /// - `BGFX_RESET_NONE` - No reset flags. - /// - `BGFX_RESET_FULLSCREEN` - Not supported yet. - /// - `BGFX_RESET_MSAA_X[2/4/8/16]` - Enable 2, 4, 8 or 16 x MSAA. /// - `BGFX_RESET_VSYNC` - Enable V-Sync. /// - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. /// - `BGFX_RESET_CAPTURE` - Begin screen capture. @@ -2482,8 +2489,16 @@ namespace bgfx /// - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip /// occurs. Default behaviour is that flip occurs before rendering new /// frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. - /// - `BGFX_RESET_SRGB_BACKBUFFER` - Enable sRGB back-buffer. - /// @param[in] _format Texture format. See: `TextureFormat::Enum`. + /// Per-surface settings are not here. `BGFX_SWAP_CHAIN_*` flags belong + /// on `SwapChain::flags`, and are ignored if passed here. + /// @param[in] _swapChain Main window swap chain. When `NULL` the main window is left + /// untouched and only the device and frame globals above are + /// applied, which is what an application driving its own swap + /// chains wants. Otherwise the main window takes on this + /// description: resize it, change its format, or change its + /// per-surface flags. Fields left neutral keep their current + /// value, and `nwh`/`ndt` are ignored -- main's are bgfx's own. + /// Must be `NULL` when `bgfx::init` created no main window. /// /// @attention This call doesn’t change the window size, it just resizes /// the back-buffer. Your windowing code controls the window size. @@ -2491,10 +2506,8 @@ namespace bgfx /// @attention C99's equivalent binding is `bgfx_reset`. /// void reset( - uint32_t _width - , uint32_t _height - , uint32_t _flags = BGFX_RESET_NONE - , TextureFormat::Enum _format = TextureFormat::Count + uint32_t _flags = BGFX_RESET_NONE + , const SwapChain* _swapChain = NULL ); /// Advance to next frame. This is the main frame-advancement call on the @@ -2628,10 +2641,17 @@ namespace bgfx /// - `BGFX_DEBUG_TEXT` - Display debug text. /// - `BGFX_DEBUG_WIREFRAME` - Wireframe rendering. All rendering /// primitives will be rendered as lines. + /// @param[in] _handle Frame buffer the debug text and statistics are drawn on. + /// Invalid handle selects the window bgfx was initialized with. + /// @param[in] _scale Debug text scale factor. 0 is the same as 1. /// /// @attention C99's equivalent binding is `bgfx_set_debug`. /// - void setDebug(uint32_t _debug); + void setDebug( + uint32_t _debug + , FrameBufferHandle _handle = BGFX_INVALID_HANDLE + , uint8_t _scale = 0 + ); /// Clear internal debug text buffer. /// @@ -3722,13 +3742,9 @@ namespace bgfx , bool _destroyTexture = false ); - /// Create frame buffer for multiple window rendering. + /// Create a frame buffer for a window, from a full swap chain description. /// - /// @param[in] _nwh OS' target native window handle. - /// @param[in] _width Window back buffer width. - /// @param[in] _height Window back buffer height. - /// @param[in] _format Window back buffer color format. - /// @param[in] _depthFormat Window back buffer depth format. + /// @param[in] _desc Swap chain description. See: `bgfx::SwapChain`. /// /// @returns Frame buffer handle. /// @@ -3737,14 +3753,27 @@ namespace bgfx /// /// @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. /// - /// @attention C99's equivalent binding is `bgfx_create_frame_buffer_from_nwh`. + /// @attention C99's equivalent binding is `bgfx_create_frame_buffer_from_swap_chain`. /// - FrameBufferHandle createFrameBuffer( - void* _nwh - , uint16_t _width - , uint16_t _height - , TextureFormat::Enum _format = TextureFormat::Count - , TextureFormat::Enum _depthFormat = TextureFormat::Count + FrameBufferHandle createFrameBuffer(const SwapChain& _desc); + + /// Change a swap chain's size, format or per-surface flags, in place. + /// + /// The frame buffer handle stays valid, so nothing that refers to it has to be + /// rebuilt. Pass `BGFX_INVALID_HANDLE` to address the window bgfx was + /// initialized with. + /// + /// @param[in] _handle Window frame buffer handle. The window bgfx was initialized + /// with is not addressed here; it is `bgfx::reset`'s swap chain. + /// @param[in] _desc Swap chain description. See: `bgfx::SwapChain`. + /// + /// @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. + /// + /// @attention C99's equivalent binding is `bgfx_update_swap_chain`. + /// + void updateSwapChain( + FrameBufferHandle _handle + , const SwapChain& _desc ); /// Set frame buffer debug name. @@ -4335,16 +4364,6 @@ namespace bgfx /// RenderFrame::Enum renderFrame(int32_t _msecs = -1); - /// Set platform data. - /// - /// @param[in] _data Platform data. - /// - /// @warning Must be called before `bgfx::init`. - /// - /// @attention C99's equivalent binding is `bgfx_set_platform_data`. - /// - void setPlatformData(const PlatformData& _data); - /// Get internal data for interop. /// /// @returns Internal data. @@ -4358,66 +4377,6 @@ namespace bgfx /// const InternalData* getInternalData(); - /// Override internal texture with externally created texture. Previously - /// created internal texture will released. - /// - /// @param[in] _handle Texture handle. - /// @param[in] _ptr Native API pointer to texture. - /// @param[in] _layerIndex Layer index for texture arrays (only implemented for D3D11). - /// - /// @returns Native API pointer to texture. If result is 0, texture is not created - /// yet from the main thread. - /// - /// @attention It's expected you understand some bgfx internals before you - /// use this call. - /// - /// @warning Must be called only on render thread. - /// - /// @attention C99's equivalent binding is `bgfx_override_internal_texture_ptr`. - /// - uintptr_t overrideInternal( - TextureHandle _handle - , uintptr_t _ptr - , uint16_t _layerIndex = 0 - ); - - /// Override internal texture by creating new texture. Previously created - /// internal texture will released. - /// - /// @param[in] _handle Texture handle. - /// @param[in] _width Width. - /// @param[in] _height Height. - /// @param[in] _numMips Number of mip-maps. - /// @param[in] _format Texture format. See: `TextureFormat::Enum`. - /// @param[in] _flags Texture creation (see `BGFX_TEXTURE_*`.), and sampler (see `BGFX_SAMPLER_*`) - /// flags. Default texture sampling mode is linear, and wrap mode is repeat. - /// - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap - /// mode. - /// - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic - /// sampling. - /// - /// @returns Native API pointer to texture. If result is 0, texture is not created - /// yet from the main thread. - /// - /// @returns Native API pointer to texture. If result is 0, texture is not created yet from the - /// main thread. - /// - /// @attention It's expected you understand some bgfx internals before you - /// use this call. - /// - /// @warning Must be called only on render thread. - /// - /// @attention C99's equivalent binding is `bgfx_override_internal_texture`. - /// - uintptr_t overrideInternal( - TextureHandle _handle - , uint16_t _width - , uint16_t _height - , uint8_t _numMips - , TextureFormat::Enum _format - , uint64_t _flags = BGFX_TEXTURE_NONE | BGFX_SAMPLER_NONE - ); - /// Sets a debug marker. This allows you to group graphics calls together for easy browsing in /// graphics debugging tools. /// diff --git a/include/bgfx/c99/bgfx.h b/include/bgfx/c99/bgfx.h index 7b0348c15..f2150be95 100644 --- a/include/bgfx/c99/bgfx.h +++ b/include/bgfx/c99/bgfx.h @@ -330,15 +330,21 @@ typedef enum bgfx_uniform_freq /** * Backbuffer ratio enum. * + * The ratio is always relative to the window bgfx was initialized with, and is + * re-resolved by `bgfx::reset`. It is not relative to whichever window a texture + * happens to be rendered to, so on a second window a ratio texture is not + * meaningfully sized. For that reason a ratio texture cannot be used as + * `SwapChain::depth`. + * */ typedef enum bgfx_backbuffer_ratio { - BGFX_BACKBUFFER_RATIO_EQUAL, /** ( 0) Equal to backbuffer. */ - BGFX_BACKBUFFER_RATIO_HALF, /** ( 1) One half size of backbuffer. */ - BGFX_BACKBUFFER_RATIO_QUARTER, /** ( 2) One quarter size of backbuffer. */ - BGFX_BACKBUFFER_RATIO_EIGHTH, /** ( 3) One eighth size of backbuffer. */ - BGFX_BACKBUFFER_RATIO_SIXTEENTH, /** ( 4) One sixteenth size of backbuffer. */ - BGFX_BACKBUFFER_RATIO_DOUBLE, /** ( 5) Double size of backbuffer. */ + BGFX_BACKBUFFER_RATIO_EQUAL, /** ( 0) Equal to the main window's backbuffer. */ + BGFX_BACKBUFFER_RATIO_HALF, /** ( 1) One half size of the main window's backbuffer. */ + BGFX_BACKBUFFER_RATIO_QUARTER, /** ( 2) One quarter size of the main window's backbuffer. */ + BGFX_BACKBUFFER_RATIO_EIGHTH, /** ( 3) One eighth size of the main window's backbuffer. */ + BGFX_BACKBUFFER_RATIO_SIXTEENTH, /** ( 4) One sixteenth size of the main window's backbuffer. */ + BGFX_BACKBUFFER_RATIO_DOUBLE, /** ( 5) Double size of the main window's backbuffer. */ BGFX_BACKBUFFER_RATIO_COUNT @@ -777,7 +783,23 @@ typedef struct bgfx_internal_data_s */ typedef struct bgfx_platform_data_s { - void* ndt; /** Native display type (*nix specific). */ + + /** + * GL context, D3D device, or Vulkan device. If `NULL`, bgfx + * will create context/device. + */ + void* context; + void* queue; /** D3D12 Queue. If `NULL` bgfx will create queue. */ + bgfx_native_window_handle_type_t type; /** Handle type. Needed for platforms having more than one option. */ + +} bgfx_platform_data_t; + +/** + * Swap chain description. + * + */ +typedef struct bgfx_swap_chain_s +{ /** * Native window handle. If `NULL`, bgfx will create a headless @@ -786,43 +808,32 @@ typedef struct bgfx_platform_data_s void* nwh; /** - * GL context, D3D device, or Vulkan device. If `NULL`, bgfx - * will create context/device. + * Native display type (*nix specific). A window that leaves this + * `NULL` uses the one the main window was initialized with. */ - void* context; - void* queue; /** D3D12 Queue. If `NULL` bgfx will create queue. */ + void* ndt; + uint32_t width; /** Swap chain width. */ + uint32_t height; /** Swap chain height. */ + uint32_t flags; /** See: `BGFX_SWAP_CHAIN_*`. */ + bgfx_texture_format_t formatColor; /** Color format. */ /** - * GL back-buffer, or D3D render target view. If `NULL` bgfx will - * create back-buffer color surface. + * Depth/stencil format, or `TextureFormat::Count` for no depth. Ignored + * when `depth` is valid. */ - void* backBuffer; + bgfx_texture_format_t formatDepthStencil; /** - * Backbuffer depth/stencil. If `NULL`, bgfx will create a back-buffer - * depth/stencil surface. + * Depth attachment. Must be created with `BGFX_TEXTURE_RT`, and match the + * swap chain width, height and sample count. When invalid, bgfx creates and + * owns a depth surface per `formatDepthStencil`. A texture supplied here is + * never destroyed by bgfx, and may be shared by several same-size swap chains. */ - void* backBufferDS; - bgfx_native_window_handle_type_t type; /** Handle type. Needed for platforms having more than one option. */ - -} bgfx_platform_data_t; - -/** - * Backbuffer resolution and reset parameters. - * - */ -typedef struct bgfx_resolution_s -{ - bgfx_texture_format_t formatColor; /** Backbuffer color format. */ - bgfx_texture_format_t formatDepthStencil; /** Backbuffer depth/stencil format. */ - uint32_t width; /** Backbuffer width. */ - uint32_t height; /** Backbuffer height. */ - uint32_t reset; /** Reset parameters. */ + bgfx_texture_handle_t depth; uint8_t numBackBuffers; /** Number of back buffers. */ uint8_t maxFrameLatency; /** Maximum frame latency. */ - uint8_t debugTextScale; /** Scale factor for debug text. */ -} bgfx_resolution_t; +} bgfx_swap_chain_t; /** * Configurable runtime limits parameters. @@ -900,7 +911,19 @@ typedef struct bgfx_init_s bool fallback; /** Enable fallback to next available renderer. */ bool videoDecode; /** Enable video decoding. */ bgfx_platform_data_t platformData; /** Platform data. */ - bgfx_resolution_t resolution; /** Backbuffer resolution and reset parameters. See: `bgfx::Resolution`. */ + + /** + * Swap chain for the window bgfx creates its device on. + * See: `bgfx::SwapChain`. + */ + bgfx_swap_chain_t swapChain; + + /** + * Device and frame global settings. Anything that is a + * property of one surface belongs in `swapChain` instead. + * See: `BGFX_RESET_*`. + */ + uint32_t reset; bgfx_init_limits_t limits; /** Configurable runtime limits parameters. */ /** @@ -1566,12 +1589,8 @@ BGFX_C_API void bgfx_shutdown(void); * @attention This call doesn’t change the window size, it just resizes * the back-buffer. Your windowing code controls the window size. * - * @param[in] _width Back-buffer width. - * @param[in] _height Back-buffer height. * @param[in] _flags See: `BGFX_RESET_*` for more info. * - `BGFX_RESET_NONE` - No reset flags. - * - `BGFX_RESET_FULLSCREEN` - Not supported yet. - * - `BGFX_RESET_MSAA_X[2/4/8/16]` - Enable 2, 4, 8 or 16 x MSAA. * - `BGFX_RESET_VSYNC` - Enable V-Sync. * - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. * - `BGFX_RESET_CAPTURE` - Begin screen capture. @@ -1579,11 +1598,19 @@ BGFX_C_API void bgfx_shutdown(void); * - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip * occurs. Default behaviour is that flip occurs before rendering new * frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. - * - `BGFX_RESET_SRGB_BACKBUFFER` - Enable sRGB back-buffer. - * @param[in] _format Texture format. See: `TextureFormat::Enum`. + * Per-surface settings are not here. `BGFX_SWAP_CHAIN_*` flags belong + * on `SwapChain::flags`, and are ignored if passed here. + * @param[in] _swapChain Main window swap chain. When `NULL` the main window is left + * untouched and only the device and frame globals above are + * applied, which is what an application driving its own swap + * chains wants. Otherwise the main window takes on this + * description: resize it, change its format, or change its + * per-surface flags. Fields left neutral keep their current + * value, and `nwh`/`ndt` are ignored -- main's are bgfx's own. + * Must be `NULL` when `bgfx::init` created no main window. * */ -BGFX_C_API void bgfx_reset(uint32_t _width, uint32_t _height, uint32_t _flags, bgfx_texture_format_t _format); +BGFX_C_API void bgfx_reset(uint32_t _flags, const bgfx_swap_chain_t* _swapChain); /** * Advance to next frame. This is the main frame-advancement call on the @@ -1721,9 +1748,12 @@ BGFX_C_API const bgfx_memory_t* bgfx_make_ref_release(const void* _data, uint32_ * - `BGFX_DEBUG_TEXT` - Display debug text. * - `BGFX_DEBUG_WIREFRAME` - Wireframe rendering. All rendering * primitives will be rendered as lines. + * @param[in] _handle Frame buffer the debug text and statistics are drawn on. + * Invalid handle selects the window bgfx was initialized with. + * @param[in] _scale Debug text scale factor. 0 is the same as 1. * */ -BGFX_C_API void bgfx_set_debug(uint32_t _debug); +BGFX_C_API void bgfx_set_debug(uint32_t _debug, bgfx_frame_buffer_handle_t _handle, uint8_t _scale); /** * Clear internal debug text buffer. @@ -2585,23 +2615,35 @@ BGFX_C_API bgfx_frame_buffer_handle_t bgfx_create_frame_buffer_from_handles(uint BGFX_C_API bgfx_frame_buffer_handle_t bgfx_create_frame_buffer_from_attachment(uint8_t _num, const bgfx_attachment_t* _attachment, bool _destroyTexture); /** - * Create frame buffer for multiple window rendering. + * Create a frame buffer for a window, from a full swap chain description. * * @remarks * Frame buffer cannot be used for sampling. * * @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. * - * @param[in] _nwh OS' target native window handle. - * @param[in] _width Window back buffer width. - * @param[in] _height Window back buffer height. - * @param[in] _format Window back buffer color format. - * @param[in] _depthFormat Window back buffer depth format. + * @param[in] _desc Swap chain description. See: `bgfx::SwapChain`. * * @returns Frame buffer handle. * */ -BGFX_C_API bgfx_frame_buffer_handle_t bgfx_create_frame_buffer_from_nwh(void* _nwh, uint16_t _width, uint16_t _height, bgfx_texture_format_t _format, bgfx_texture_format_t _depthFormat); +BGFX_C_API bgfx_frame_buffer_handle_t bgfx_create_frame_buffer_from_swap_chain(const bgfx_swap_chain_t* _desc); + +/** + * Change a swap chain's size, format or per-surface flags, in place. + * + * The frame buffer handle stays valid, so nothing that refers to it has to be + * rebuilt. Pass `BGFX_INVALID_HANDLE` to address the window bgfx was + * initialized with. + * + * @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. + * + * @param[in] _handle Window frame buffer handle. The window bgfx was initialized + * with is not addressed here; it is `bgfx::reset`'s swap chain. + * @param[in] _desc Swap chain description. See: `bgfx::SwapChain`. + * + */ +BGFX_C_API void bgfx_update_swap_chain(bgfx_frame_buffer_handle_t _handle, const bgfx_swap_chain_t* _desc); /** * Set frame buffer debug name. @@ -3689,16 +3731,6 @@ BGFX_C_API void bgfx_request_screen_shot(bgfx_frame_buffer_handle_t _handle, con */ BGFX_C_API bgfx_render_frame_t bgfx_render_frame(int32_t _msecs); -/** - * Set platform data. - * - * @warning Must be called before `bgfx::init`. - * - * @param[in] _data Platform data. - * - */ -BGFX_C_API void bgfx_set_platform_data(const bgfx_platform_data_t * _data); - /** * Get internal data for interop. * @@ -3710,55 +3742,6 @@ BGFX_C_API void bgfx_set_platform_data(const bgfx_platform_data_t * _data); */ BGFX_C_API const bgfx_internal_data_t* bgfx_get_internal_data(void); -/** - * Override internal texture with externally created texture. Previously - * created internal texture will released. - * - * @attention It's expected you understand some bgfx internals before you - * use this call. - * - * @warning Must be called only on render thread. - * - * @param[in] _handle Texture handle. - * @param[in] _ptr Native API pointer to texture. - * @param[in] _layerIndex Layer index for texture arrays (only implemented for D3D11). - * - * @returns Native API pointer to texture. If result is 0, texture is not created - * yet from the main thread. - * - */ -BGFX_C_API uintptr_t bgfx_override_internal_texture_ptr(bgfx_texture_handle_t _handle, uintptr_t _ptr, uint16_t _layerIndex); - -/** - * Override internal texture by creating new texture. Previously created - * internal texture will released. - * - * @attention It's expected you understand some bgfx internals before you - * use this call. - * - * @returns Native API pointer to texture. If result is 0, texture is not created yet from the - * main thread. - * - * @warning Must be called only on render thread. - * - * @param[in] _handle Texture handle. - * @param[in] _width Width. - * @param[in] _height Height. - * @param[in] _numMips Number of mip-maps. - * @param[in] _format Texture format. See: `TextureFormat::Enum`. - * @param[in] _flags Texture creation (see `BGFX_TEXTURE_*`.), and sampler (see `BGFX_SAMPLER_*`) - * flags. Default texture sampling mode is linear, and wrap mode is repeat. - * - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap - * mode. - * - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic - * sampling. - * - * @returns Native API pointer to texture. If result is 0, texture is not created - * yet from the main thread. - * - */ -BGFX_C_API uintptr_t bgfx_override_internal_texture(bgfx_texture_handle_t _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, bgfx_texture_format_t _format, uint64_t _flags); - /** * Sets a debug marker. This allows you to group graphics calls together for easy browsing in * graphics debugging tools. @@ -4455,7 +4438,8 @@ typedef enum bgfx_function_id BGFX_FUNCTION_ID_CREATE_FRAME_BUFFER_SCALED, BGFX_FUNCTION_ID_CREATE_FRAME_BUFFER_FROM_HANDLES, BGFX_FUNCTION_ID_CREATE_FRAME_BUFFER_FROM_ATTACHMENT, - BGFX_FUNCTION_ID_CREATE_FRAME_BUFFER_FROM_NWH, + BGFX_FUNCTION_ID_CREATE_FRAME_BUFFER_FROM_SWAP_CHAIN, + BGFX_FUNCTION_ID_UPDATE_SWAP_CHAIN, BGFX_FUNCTION_ID_SET_FRAME_BUFFER_NAME, BGFX_FUNCTION_ID_GET_TEXTURE, BGFX_FUNCTION_ID_DESTROY_FRAME_BUFFER, @@ -4532,10 +4516,7 @@ typedef enum bgfx_function_id BGFX_FUNCTION_ID_ENCODER_BLIT_FROM_BUFFER, BGFX_FUNCTION_ID_REQUEST_SCREEN_SHOT, BGFX_FUNCTION_ID_RENDER_FRAME, - BGFX_FUNCTION_ID_SET_PLATFORM_DATA, BGFX_FUNCTION_ID_GET_INTERNAL_DATA, - BGFX_FUNCTION_ID_OVERRIDE_INTERNAL_TEXTURE_PTR, - BGFX_FUNCTION_ID_OVERRIDE_INTERNAL_TEXTURE, BGFX_FUNCTION_ID_SET_MARKER, BGFX_FUNCTION_ID_SET_STATE, BGFX_FUNCTION_ID_SET_CONDITION, @@ -4612,7 +4593,7 @@ struct bgfx_interface_vtbl void (*init_ctor)(bgfx_init_t* _init); bool (*init)(const bgfx_init_t * _init); void (*shutdown)(void); - void (*reset)(uint32_t _width, uint32_t _height, uint32_t _flags, bgfx_texture_format_t _format); + void (*reset)(uint32_t _flags, const bgfx_swap_chain_t* _swapChain); uint32_t (*frame)(uint8_t _flags); bgfx_renderer_type_t (*get_renderer_type)(void); const bgfx_caps_t* (*get_caps)(void); @@ -4621,7 +4602,7 @@ struct bgfx_interface_vtbl const bgfx_memory_t* (*copy)(const void* _data, uint32_t _size); const bgfx_memory_t* (*make_ref)(const void* _data, uint32_t _size); const bgfx_memory_t* (*make_ref_release)(const void* _data, uint32_t _size, bgfx_release_fn_t _releaseFn, void* _userData); - void (*set_debug)(uint32_t _debug); + void (*set_debug)(uint32_t _debug, bgfx_frame_buffer_handle_t _handle, uint8_t _scale); void (*dbg_text_clear)(uint8_t _attr, bool _small); void (*dbg_text_printf)(uint16_t _x, uint16_t _y, uint8_t _attr, const char* _format, ... ); void (*dbg_text_vprintf)(uint16_t _x, uint16_t _y, uint8_t _attr, const char* _format, va_list _argList); @@ -4680,7 +4661,8 @@ struct bgfx_interface_vtbl bgfx_frame_buffer_handle_t (*create_frame_buffer_scaled)(bgfx_backbuffer_ratio_t _ratio, bgfx_texture_format_t _format, uint64_t _textureFlags); bgfx_frame_buffer_handle_t (*create_frame_buffer_from_handles)(uint8_t _num, const bgfx_texture_handle_t* _handles, bool _destroyTexture); bgfx_frame_buffer_handle_t (*create_frame_buffer_from_attachment)(uint8_t _num, const bgfx_attachment_t* _attachment, bool _destroyTexture); - bgfx_frame_buffer_handle_t (*create_frame_buffer_from_nwh)(void* _nwh, uint16_t _width, uint16_t _height, bgfx_texture_format_t _format, bgfx_texture_format_t _depthFormat); + bgfx_frame_buffer_handle_t (*create_frame_buffer_from_swap_chain)(const bgfx_swap_chain_t* _desc); + void (*update_swap_chain)(bgfx_frame_buffer_handle_t _handle, const bgfx_swap_chain_t* _desc); void (*set_frame_buffer_name)(bgfx_frame_buffer_handle_t _handle, const char* _name, int32_t _len); bgfx_texture_handle_t (*get_texture)(bgfx_frame_buffer_handle_t _handle, uint8_t _attachment); void (*destroy_frame_buffer)(bgfx_frame_buffer_handle_t _handle); @@ -4757,10 +4739,7 @@ struct bgfx_interface_vtbl void (*encoder_blit_from_buffer)(bgfx_encoder_t* _this, bgfx_view_id_t _id, const bgfx_texture_region_t * _dst, const bgfx_buffer_region_t * _src); void (*request_screen_shot)(bgfx_frame_buffer_handle_t _handle, const char* _filePath); bgfx_render_frame_t (*render_frame)(int32_t _msecs); - void (*set_platform_data)(const bgfx_platform_data_t * _data); const bgfx_internal_data_t* (*get_internal_data)(void); - uintptr_t (*override_internal_texture_ptr)(bgfx_texture_handle_t _handle, uintptr_t _ptr, uint16_t _layerIndex); - uintptr_t (*override_internal_texture)(bgfx_texture_handle_t _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, bgfx_texture_format_t _format, uint64_t _flags); void (*set_marker)(const char* _name, int32_t _len); void (*set_state)(uint64_t _state, uint32_t _rgba); void (*set_condition)(bgfx_occlusion_query_handle_t _handle, bool _visible); diff --git a/include/bgfx/defines.h b/include/bgfx/defines.h index b6d63a496..905944107 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(157) +#define BGFX_API_VERSION UINT32_C(158) /** * Color RGB/alpha/depth write. When it's not specified write will be disabled. @@ -433,6 +433,23 @@ #define BGFX_RESET_RESERVED_SHIFT 31 //!< Internal bit shift #define BGFX_RESET_RESERVED_MASK UINT32_C(0x80000000) //!< Internal bit mask +#define BGFX_SWAP_CHAIN_MSAA_X2 UINT32_C(0x00000010) //!< Enable 2x MSAA. +#define BGFX_SWAP_CHAIN_MSAA_X4 UINT32_C(0x00000020) //!< Enable 4x MSAA. +#define BGFX_SWAP_CHAIN_MSAA_X8 UINT32_C(0x00000030) //!< Enable 8x MSAA. +#define BGFX_SWAP_CHAIN_MSAA_X16 UINT32_C(0x00000040) //!< Enable 16x MSAA. +#define BGFX_SWAP_CHAIN_MSAA_SHIFT 4 +#define BGFX_SWAP_CHAIN_MSAA_MASK UINT32_C(0x00000070) + +#define BGFX_SWAP_CHAIN_NONE UINT32_C(0x00000000) //!< No swap chain flags. +#define BGFX_SWAP_CHAIN_FULLSCREEN UINT32_C(0x00000001) //!< Not supported yet. +#define BGFX_SWAP_CHAIN_SRGB_BACKBUFFER UINT32_C(0x00008000) //!< Enable sRGB backbuffer. +#define BGFX_SWAP_CHAIN_HDR10 UINT32_C(0x00010000) //!< Enable HDR10 rendering. +#define BGFX_SWAP_CHAIN_HIDPI UINT32_C(0x00020000) //!< Enable HiDPI rendering. +#define BGFX_SWAP_CHAIN_TRANSPARENT_BACKBUFFER UINT32_C(0x00100000) //!< Transparent backbuffer. Availability depends on: `BGFX_CAPS_TRANSPARENT_BACKBUFFER`. + +#define BGFX_SWAP_CHAIN_FULLSCREEN_SHIFT 0 +#define BGFX_SWAP_CHAIN_FULLSCREEN_MASK UINT32_C(0x00000001) + #define BGFX_CAPS_ALPHA_TO_COVERAGE UINT64_C(0x0000000000000001) //!< Alpha to coverage is supported. #define BGFX_CAPS_BLEND_INDEPENDENT UINT64_C(0x0000000000000002) //!< Blend independent is supported. #define BGFX_CAPS_COMPUTE UINT64_C(0x0000000000000004) //!< Compute shaders are supported. diff --git a/scripts/bgfx.idl b/scripts/bgfx.idl index 477f4d4bf..95f81ca68 100644 --- a/scripts/bgfx.idl +++ b/scripts/bgfx.idl @@ -1,7 +1,7 @@ -- vim: syntax=lua -- bgfx interface -version(157) +version(158) typedef "bool" typedef "char" @@ -350,6 +350,25 @@ flag.ResetFullscreen { bits = 32, shift = 0, range = 1, base = 1 } flag.ResetReserved { bits = 32, shift = 31, range = 1, desc = "Internal" } +flag.SwapChainMsaa { bits = 32, shift = 4, range = 3, base = 1 } + .X2 --- Enable 2x MSAA. + .X4 --- Enable 4x MSAA. + .X8 --- Enable 8x MSAA. + .X16 --- Enable 16x MSAA. + () + +flag.SwapChain { bits = 32, section = "Swap Chain" } + .None ( 0) --- No swap chain flags. + .Fullscreen ( 1) --- Not supported yet. + .SrgbBackbuffer (16) --- Enable sRGB backbuffer. + .Hdr10 (17) --- Enable HDR10 rendering. + .Hidpi (18) --- Enable HiDPI rendering. + .TransparentBackbuffer (21) --- Transparent backbuffer. Availability depends on: `BGFX_CAPS_TRANSPARENT_BACKBUFFER`. + () + +flag.SwapChainFullscreen { bits = 32, shift = 0, range = 1, base = 1 } + () + flag.Caps { bits = 64, base = 1, name = "Caps", section = "Available Caps" } .AlphaToCoverage --- Alpha to coverage is supported. .BlendIndependent --- Blend independent is supported. @@ -695,13 +714,19 @@ enum.UniformFreq { comment = "Uniform frequency:", section = "Uniforms" () --- Backbuffer ratio enum. +--- +--- The ratio is always relative to the window bgfx was initialized with, and is +--- re-resolved by `bgfx::reset`. It is not relative to whichever window a texture +--- happens to be rendered to, so on a second window a ratio texture is not +--- meaningfully sized. For that reason a ratio texture cannot be used as +--- `SwapChain::depth`. enum.BackbufferRatio { comment = "Backbuffer ratios:" } - .Equal --- Equal to backbuffer. - .Half --- One half size of backbuffer. - .Quarter --- One quarter size of backbuffer. - .Eighth --- One eighth size of backbuffer. - .Sixteenth --- One sixteenth size of backbuffer. - .Double --- Double size of backbuffer. + .Equal --- Equal to the main window's backbuffer. + .Half --- One half size of the main window's backbuffer. + .Quarter --- One quarter size of the main window's backbuffer. + .Eighth --- One eighth size of the main window's backbuffer. + .Sixteenth --- One sixteenth size of the main window's backbuffer. + .Double --- Double size of the main window's backbuffer. () --- Occlusion query result. @@ -882,33 +907,33 @@ struct.InternalData { section = "Platform specific" } --- Platform data. struct.PlatformData { ctor, section = "Platform specific" } - .ndt "void*" --- Native display type (*nix specific). - .nwh "void*" - --- Native window handle. If `NULL`, bgfx will create a headless - --- context/device, provided the rendering API supports it. .context "void*" --- GL context, D3D device, or Vulkan device. If `NULL`, bgfx --- will create context/device. .queue "void*" --- D3D12 Queue. If `NULL` bgfx will create queue. - .backBuffer "void*" - --- GL back-buffer, or D3D render target view. If `NULL` bgfx will - --- create back-buffer color surface. - .backBufferDS "void*" - --- Backbuffer depth/stencil. If `NULL`, bgfx will create a back-buffer - --- depth/stencil surface. .type "NativeWindowHandleType::Enum" --- Handle type. Needed for platforms having more than one option. ---- Backbuffer resolution and reset parameters. -struct.Resolution { ctor, section = "Initialization and Shutdown" } - .formatColor "TextureFormat::Enum" --- Backbuffer color format. - .formatDepthStencil "TextureFormat::Enum" --- Backbuffer depth/stencil format. - .width "uint32_t" --- Backbuffer width. - .height "uint32_t" --- Backbuffer height. - .reset "uint32_t" --- Reset parameters. +--- Swap chain description. +struct.SwapChain { ctor, section = "Swap Chain" } + .nwh "void*" --- Native window handle. If `NULL`, bgfx will create a headless + --- context/device, provided the rendering API supports it. + .ndt "void*" --- Native display type (*nix specific). A window that leaves this + --- `NULL` uses the one the main window was initialized with. + .width "uint32_t" --- Swap chain width. + .height "uint32_t" --- Swap chain height. + .flags "uint32_t" --- See: `BGFX_SWAP_CHAIN_*`. + .formatColor "TextureFormat::Enum" --- Color format. + .formatDepthStencil "TextureFormat::Enum" + --- Depth/stencil format, or `TextureFormat::Count` for no depth. Ignored + --- when `depth` is valid. + .depth "TextureHandle" + --- Depth attachment. Must be created with `BGFX_TEXTURE_RT`, and match the + --- swap chain width, height and sample count. When invalid, bgfx creates and + --- owns a depth surface per `formatDepthStencil`. A texture supplied here is + --- never destroyed by bgfx, and may be shared by several same-size swap chains. .numBackBuffers "uint8_t" --- Number of back buffers. .maxFrameLatency "uint8_t" --- Maximum frame latency. - .debugTextScale "uint8_t" --- Scale factor for debug text. --- Configurable runtime limits parameters. struct.Limits { ctor, namespace = "Init" } @@ -958,7 +983,11 @@ struct.Init { ctor, section = "Initialization and Shutdown" } .fallback "bool" --- Enable fallback to next available renderer. .videoDecode "bool" --- Enable video decoding. .platformData "PlatformData" --- Platform data. - .resolution "Resolution" --- Backbuffer resolution and reset parameters. See: `bgfx::Resolution`. + .swapChain "SwapChain" --- Swap chain for the window bgfx creates its device on. + --- See: `bgfx::SwapChain`. + .reset "uint32_t" --- Device and frame global settings. Anything that is a + --- property of one surface belongs in `swapChain` instead. + --- See: `BGFX_RESET_*`. .limits "Limits" --- Configurable runtime limits parameters. .callback "CallbackI*" --- Provide application specific callback interface. --- See: `bgfx::CallbackI` @@ -1452,12 +1481,8 @@ func.shutdown { section = "Initialization and Shutdown" } --- func.reset { section = "Reset" } "void" - .width "uint32_t" --- Back-buffer width. - .height "uint32_t" --- Back-buffer height. - .flags "uint32_t" --- See: `BGFX_RESET_*` for more info. + .flags "uint32_t" --- See: `BGFX_RESET_*` for more info. { default = "BGFX_RESET_NONE" } --- - `BGFX_RESET_NONE` - No reset flags. - --- - `BGFX_RESET_FULLSCREEN` - Not supported yet. - --- - `BGFX_RESET_MSAA_X[2/4/8/16]` - Enable 2, 4, 8 or 16 x MSAA. --- - `BGFX_RESET_VSYNC` - Enable V-Sync. --- - `BGFX_RESET_MAXANISOTROPY` - Turn on/off max anisotropy. --- - `BGFX_RESET_CAPTURE` - Begin screen capture. @@ -1465,9 +1490,18 @@ func.reset { section = "Reset" } --- - `BGFX_RESET_FLIP_AFTER_RENDER` - This flag specifies where flip --- occurs. Default behaviour is that flip occurs before rendering new --- frame. This flag only has effect when `BGFX_CONFIG_MULTITHREADED=0`. - --- - `BGFX_RESET_SRGB_BACKBUFFER` - Enable sRGB back-buffer. - .format "TextureFormat::Enum" --- Texture format. See: `TextureFormat::Enum`. - { default = "TextureFormat::Count" } + --- + --- Per-surface settings are not here. `BGFX_SWAP_CHAIN_*` flags belong + --- on `SwapChain::flags`, and are ignored if passed here. + .swapChain "const SwapChain*" --- Main window swap chain. When `NULL` the main window is left + { default = NULL } --- untouched and only the device and frame globals above are + --- applied, which is what an application driving its own swap + --- chains wants. Otherwise the main window takes on this + --- description: resize it, change its format, or change its + --- per-surface flags. Fields left neutral keep their current + --- value, and `nwh`/`ndt` are ignored -- main's are bgfx's own. + --- + --- Must be `NULL` when `bgfx::init` created no main window. --- Advance to next frame. This is the main frame-advancement call on the --- API thread (the thread from which `bgfx::init` was called). @@ -1582,6 +1616,11 @@ func.setDebug { section = "Debug Features" } --- - `BGFX_DEBUG_TEXT` - Display debug text. --- - `BGFX_DEBUG_WIREFRAME` - Wireframe rendering. All rendering --- primitives will be rendered as lines. + .handle "FrameBufferHandle" --- Frame buffer the debug text and statistics are drawn on. + --- Invalid handle selects the window bgfx was initialized with. + { default = "BGFX_INVALID_HANDLE" } + .scale "uint8_t" --- Debug text scale factor. 0 is the same as 1. + { default = 0 } --- Clear internal debug text buffer. func.dbgTextClear { section = "Debug Text Display" } @@ -2249,22 +2288,30 @@ func.createFrameBuffer { cname = "create_frame_buffer_from_attachment", section .destroyTexture "bool" --- If true, textures will be destroyed when { default = false } --- frame buffer is destroyed. ---- Create frame buffer for multiple window rendering. +--- Create a frame buffer for a window, from a full swap chain description. --- --- @remarks --- Frame buffer cannot be used for sampling. --- --- @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. --- -func.createFrameBuffer { cname = "create_frame_buffer_from_nwh", section = "Frame Buffers" } - "FrameBufferHandle" --- Frame buffer handle. - .nwh "void*" --- OS' target native window handle. - .width "uint16_t" --- Window back buffer width. - .height "uint16_t" --- Window back buffer height. - .format "TextureFormat::Enum" --- Window back buffer color format. - { default = "TextureFormat::Count" } - .depthFormat "TextureFormat::Enum" --- Window back buffer depth format. - { default = "TextureFormat::Count" } +func.createFrameBuffer { cname = "create_frame_buffer_from_swap_chain", section = "Swap Chain" } + "FrameBufferHandle" --- Frame buffer handle. + .desc "const SwapChain&" --- Swap chain description. See: `bgfx::SwapChain`. + +--- Change a swap chain's size, format or per-surface flags, in place. +--- +--- The frame buffer handle stays valid, so nothing that refers to it has to be +--- rebuilt. Pass `BGFX_INVALID_HANDLE` to address the window bgfx was +--- initialized with. +--- +--- @attention Availability depends on: `BGFX_CAPS_SWAP_CHAIN`. +--- +func.updateSwapChain { section = "Swap Chain" } + "void" + .handle "FrameBufferHandle" --- Window frame buffer handle. The window bgfx was initialized + --- with is not addressed here; it is `bgfx::reset`'s swap chain. + .desc "const SwapChain&" --- Swap chain description. See: `bgfx::SwapChain`. --- Set frame buffer debug name. func.setName { cname = "set_frame_buffer_name", section = "Frame Buffers" } @@ -3231,14 +3278,6 @@ func.renderFrame { section = "Platform specific" } .msecs "int32_t" --- Timeout in milliseconds. { default = -1 } ---- Set platform data. ---- ---- @warning Must be called before `bgfx::init`. ---- -func.setPlatformData { section = "Platform specific" } - "void" - .data "const PlatformData &" --- Platform data. - --- Get internal data for interop. --- --- @attention It's expected you understand some bgfx internals before you @@ -3249,49 +3288,6 @@ func.setPlatformData { section = "Platform specific" } func.getInternalData { section = "Platform specific" } "const InternalData*" --- Internal data. ---- Override internal texture with externally created texture. Previously ---- created internal texture will released. ---- ---- @attention It's expected you understand some bgfx internals before you ---- use this call. ---- ---- @warning Must be called only on render thread. ---- -func.overrideInternal { cname = "override_internal_texture_ptr", section = "Platform specific" } - "uintptr_t" --- Native API pointer to texture. If result is 0, texture is not created - --- yet from the main thread. - .handle "TextureHandle" --- Texture handle. - .ptr "uintptr_t" --- Native API pointer to texture. - .layerIndex "uint16_t" --- Layer index for texture arrays (only implemented for D3D11). - { default = 0 } - ---- Override internal texture by creating new texture. Previously created ---- internal texture will released. ---- ---- @attention It's expected you understand some bgfx internals before you ---- use this call. ---- ---- @returns Native API pointer to texture. If result is 0, texture is not created yet from the ---- main thread. ---- ---- @warning Must be called only on render thread. ---- -func.overrideInternal { cname = "override_internal_texture", section = "Platform specific" } - "uintptr_t" --- Native API pointer to texture. If result is 0, texture is not created - --- yet from the main thread. - .handle "TextureHandle" --- Texture handle. - .width "uint16_t" --- Width. - .height "uint16_t" --- Height. - .numMips "uint8_t" --- Number of mip-maps. - .format "TextureFormat::Enum" --- Texture format. See: `TextureFormat::Enum`. - .flags "uint64_t" --- Texture creation (see `BGFX_TEXTURE_*`.), and sampler (see `BGFX_SAMPLER_*`) - --- flags. Default texture sampling mode is linear, and wrap mode is repeat. - --- - `BGFX_SAMPLER_[U/V/W]_[MIRROR/CLAMP]` - Mirror or clamp to edge wrap - --- mode. - --- - `BGFX_SAMPLER_[MIN/MAG/MIP]_[POINT/ANISOTROPIC]` - Point or anisotropic - --- sampling. - { default = "BGFX_TEXTURE_NONE | BGFX_SAMPLER_NONE" } - -- Legacy API: --- Sets a debug marker. This allows you to group graphics calls together for easy browsing in @@ -3865,6 +3861,10 @@ section("Updating", 2) --- Reset flags control back-buffer resolution, MSAA, vsync, and other global rendering settings. section("Reset", 3) +--- Swap chain flags control properties of a single presentation surface. They are numerically +--- identical to their ``BGFX_RESET_*`` counterparts, so main's flags round-trip losslessly. +section("Swap Chain", 3) + --- Frame flags and the ``bgfx::frame`` call to advance to the next frame. section("Frame", 3) diff --git a/scripts/bindings-bf.lua b/scripts/bindings-bf.lua index 69a069d61..762a0cf72 100644 --- a/scripts/bindings-bf.lua +++ b/scripts/bindings-bf.lua @@ -136,7 +136,7 @@ function gen.gen() return r end -local combined = { "State", "Stencil", "Buffer", "Texture", "Sampler", "Reset" } +local combined = { "State", "Stencil", "Buffer", "Texture", "Sampler", "Reset", "SwapChain" } for _, v in ipairs(combined) do combined[v] = {} @@ -276,7 +276,10 @@ function converter.types(typ) enum["[" .. typ.typename .. "::Count]"] = #typ.enum elseif typ.bits ~= nil then - local prefix, name = typ.name:match "(%u%l+)(.*)" + local prefix, name = typ.name:match "(%u%l+%u%l+)(.*)" + if not combined[prefix] then + prefix, name = typ.name:match "(%u%l+)(.*)" + end if prefix ~= lastCombinedFlag then lastCombinedFlagBlock() lastCombinedFlag = prefix diff --git a/scripts/bindings-c3.lua b/scripts/bindings-c3.lua index 281e63595..67aa22ad2 100644 --- a/scripts/bindings-c3.lua +++ b/scripts/bindings-c3.lua @@ -109,7 +109,7 @@ function gen.gen() return r end -local combined = { "State", "Stencil", "Buffer", "Texture", "Sampler", "Reset" } +local combined = { "State", "Stencil", "Buffer", "Texture", "Sampler", "Reset", "SwapChain" } for _, v in ipairs(combined) do combined[v] = {} @@ -254,7 +254,10 @@ function converter.types(typ) enum["[" .. typ.typename .. "::Count]"] = #typ.enum elseif typ.bits ~= nil then - local prefix, name = typ.name:match "(%u%l+)(.*)" + local prefix, name = typ.name:match "(%u%l+%u%l+)(.*)" + if not combined[prefix] then + prefix, name = typ.name:match "(%u%l+)(.*)" + end if prefix ~= lastCombinedFlag then lastCombinedFlagBlock() lastCombinedFlag = prefix diff --git a/scripts/bindings-cs.lua b/scripts/bindings-cs.lua index 116d8ca2b..0b8f067d6 100644 --- a/scripts/bindings-cs.lua +++ b/scripts/bindings-cs.lua @@ -169,7 +169,7 @@ function gen.gen_dllname() return csharp_dllname_template end -local combined = { "State", "Stencil", "Buffer", "Texture", "Sampler", "Reset" } +local combined = { "State", "Stencil", "Buffer", "Texture", "Sampler", "Reset", "SwapChain" } for _, v in ipairs(combined) do combined[v] = {} @@ -308,7 +308,10 @@ function converter.types(typ) enum["[" .. typ.typename .. "::Count]"] = #typ.enum elseif typ.bits ~= nil then - local prefix, name = typ.name:match "(%u%l+)(.*)" + local prefix, name = typ.name:match "(%u%l+%u%l+)(.*)" + if not combined[prefix] then + prefix, name = typ.name:match "(%u%l+)(.*)" + end if prefix ~= lastCombinedFlag then lastCombinedFlagBlock() lastCombinedFlag = prefix diff --git a/scripts/bindings-zig.lua b/scripts/bindings-zig.lua index e7dba8594..b712d829c 100644 --- a/scripts/bindings-zig.lua +++ b/scripts/bindings-zig.lua @@ -214,7 +214,7 @@ function gen.gen() return r end -local combined = { "State", "Stencil", "Buffer", "Texture", "Sampler", "Reset" } +local combined = { "State", "Stencil", "Buffer", "Texture", "Sampler", "Reset", "SwapChain" } for _, v in ipairs(combined) do combined[v] = {} @@ -317,7 +317,10 @@ function converter.types(params) enum["[" .. typ.typename .. "::Count]"] = #typ.enum elseif typ.bits ~= nil then - local prefix, name = typ.name:match "(%u%l+)(.*)" + local prefix, name = typ.name:match "(%u%l+%u%l+)(.*)" + if not combined[prefix] then + prefix, name = typ.name:match "(%u%l+)(.*)" + end if prefix ~= lastCombinedFlag then lastCombinedFlagBlock() lastCombinedFlag = prefix diff --git a/src/bgfx.cpp b/src/bgfx.cpp index f0355ba68..e1650ca39 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -398,7 +398,6 @@ namespace bgfx static bool s_renderFrameCalled = false; InternalData g_internalData; PlatformData g_platformData; - bool g_platformDataChangedSinceReset = false; static Handle::TypeName s_typeName[] = { @@ -443,74 +442,11 @@ namespace bgfx #endif // BGFX_CONFIG_MEMORY_TRACKING } - void setPlatformData(const PlatformData& _data) - { - if (NULL != s_ctx) - { - BGFX_FATAL(true - && g_platformData.ndt == _data.ndt - && g_platformData.context == _data.context - , Fatal::UnableToInitialize - , "Only backbuffer pointer and native window handle can be changed after initialization!" - ); - } - bx::memCopy(&g_platformData, &_data, sizeof(PlatformData) ); - g_platformDataChangedSinceReset = true; - } - const InternalData* getInternalData() { return &g_internalData; } - uintptr_t overrideInternal(TextureHandle _handle, uintptr_t _ptr, uint16_t _layerIndex) - { - BGFX_CHECK_RENDER_THREAD(); - RendererContextI* rci = s_ctx->m_renderCtx; - if (0 == rci->getInternal(_handle) ) - { - return 0; - } - - rci->overrideInternal(_handle, _ptr, _layerIndex); - - return rci->getInternal(_handle); - } - - uintptr_t overrideInternal(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint64_t _flags) - { - BGFX_CHECK_RENDER_THREAD(); - RendererContextI* rci = s_ctx->m_renderCtx; - if (0 == rci->getInternal(_handle) ) - { - return 0; - } - - uint32_t size = sizeof(uint32_t) + sizeof(TextureCreate); - Memory* mem = const_cast(alloc(size) ); - - bx::StaticMemoryBlockWriter writer(mem->data, mem->size); - bx::write(&writer, kChunkMagicTex, bx::ErrorAssert{}); - - TextureCreate tc; - tc.m_width = _width; - tc.m_height = _height; - tc.m_depth = 0; - tc.m_numLayers = 1; - tc.m_numMips = bx::max(1, _numMips); - tc.m_format = _format; - tc.m_cubeMap = false; - tc.m_mem = NULL; - bx::write(&writer, tc, bx::ErrorAssert{}); - - rci->destroyTexture(_handle); - rci->createTexture(_handle, mem, _flags, 0, 0); - - release(mem); - - return rci->getInternal(_handle); - } - void setGraphicsDebuggerPresent(bool _present) { BX_TRACE("Graphics debugger is %spresent.", _present ? "" : "not "); @@ -796,7 +732,7 @@ namespace bgfx static constexpr uint32_t kNumBatchVertices = kNumCharsPerBatch*4; static constexpr uint32_t kNumBatchIndices = kNumCharsPerBatch*6; - void TextVideoMemBlitter::init(uint8_t scale) + void TextVideoMemBlitter::init() { BGFX_CHECK_API_THREAD(); m_layout @@ -836,7 +772,6 @@ namespace bgfx m_vb = s_ctx->createTransientVertexBuffer(kNumBatchVertices*m_layout.m_stride, &m_layout); m_ib = s_ctx->createTransientIndexBuffer(kNumBatchIndices*2); - m_scale = bx::max(scale, 1); m_usedData = 0; } @@ -899,7 +834,7 @@ namespace bgfx }; static_assert(BX_COUNTOF(s_paletteLinear) == 16); - void dbgTextSubmit(RendererContextI* _renderCtx, TextVideoMemBlitter& _blitter, const TextVideoMem& _mem) + void dbgTextSubmit(RendererContextI* _renderCtx, TextVideoMemBlitter& _blitter, const TextVideoMem& _mem, FrameBufferHandle _handle, uint8_t _scale) { struct Vertex { @@ -919,12 +854,18 @@ namespace bgfx const float texelHeight = 1.0f/24.0f; const float utop = (_mem.m_small ? 0.0f : 8.0f)*texelHeight; const float ubottom = (_mem.m_small ? 8.0f : 24.0f)*texelHeight; - const float fontHeight = (_mem.m_small ? 8.0f : 16.0f)*_blitter.m_scale; - const float fontWidth = 8.0f * _blitter.m_scale; + const uint8_t scale = bx::max(_scale, 1); + const float fontHeight = (_mem.m_small ? 8.0f : 16.0f)*scale; + const float fontWidth = 8.0f * scale; - _renderCtx->dbgTextRenderBegin(_blitter); + _renderCtx->dbgTextRenderBegin(_blitter, _handle); - const uint32_t* palette = 0 != (s_ctx->m_init.resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) + const uint32_t surfaceFlags = isValid(_handle) + ? s_ctx->m_frameBufferRef[_handle.idx].m_swapChain.flags + : s_ctx->m_init.reset + ; + + const uint32_t* palette = 0 != (surfaceFlags & BGFX_SWAP_CHAIN_SRGB_BACKBUFFER) ? s_paletteLinear : s_paletteSrgb ; @@ -1783,7 +1724,7 @@ namespace bgfx for (uint32_t ii = 0, num = m_numUsedViews; ii < num; ++ii) { View& view = m_view[m_usedViews[ii] ]; - Rect rect(0, 0, uint16_t(m_resolution.width), uint16_t(m_resolution.height) ); + Rect rect(0, 0, uint16_t(m_mainSwapChain.width), uint16_t(m_mainSwapChain.height) ); if (isValid(view.m_fbh) ) { @@ -1856,7 +1797,7 @@ namespace bgfx BGFX_PROFILER_SCOPE("bgfx/DedupBind", kColorSubmit); Context::BindHashMap& bindHashMap = s_ctx->m_renderBindHashMap; - bindHashMap.reset(); + bindHashMap.clear(); RenderItemCount* remap = s_ctx->m_tempValues; @@ -2234,39 +2175,41 @@ namespace bgfx BX_TRACE(""); } - void dump(const Resolution& _resolution) + void dump(const SwapChain& _swapChain, uint32_t _reset) { - const uint32_t reset = _resolution.reset; - const uint32_t msaa = (reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; - BX_UNUSED(reset, msaa); + const uint32_t reset = _reset; + const uint32_t flags = _swapChain.flags; + const uint32_t msaa = (flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT; + BX_UNUSED(reset, flags, msaa); BX_TRACE("Reset back-buffer swap chain:"); BX_TRACE("\t%dx%d, formatColor: %s, formatDepthStencil: %s, numBackBuffers: %d, maxFrameLatency: %d" - , _resolution.width - , _resolution.height - , TextureFormat::Count == _resolution.formatColor + , _swapChain.width + , _swapChain.height + , TextureFormat::Count == _swapChain.formatColor ? "*default*" - : bimg::getName(bimg::TextureFormat::Enum(_resolution.formatColor) ) - , TextureFormat::Count == _resolution.formatDepthStencil + : bimg::getName(bimg::TextureFormat::Enum(_swapChain.formatColor) ) + , TextureFormat::Count == _swapChain.formatDepthStencil ? "*default*" - : bimg::getName(bimg::TextureFormat::Enum(_resolution.formatDepthStencil) ) - , _resolution.numBackBuffers - , _resolution.maxFrameLatency + : bimg::getName(bimg::TextureFormat::Enum(_swapChain.formatDepthStencil) ) + , _swapChain.numBackBuffers + , _swapChain.maxFrameLatency ); - BX_TRACE("\t[%c] MSAAx%d", 0 != msaa ? 'x' : ' ', 1<(_init.resolution.numBackBuffers, 2, BGFX_CONFIG_MAX_BACK_BUFFERS); - m_init.resolution.maxFrameLatency = bx::min(_init.resolution.maxFrameLatency, BGFX_CONFIG_MAX_FRAME_LATENCY); - m_init.resolution.debugTextScale = bx::clamp(_init.resolution.debugTextScale, 1, BGFX_CONFIG_DEBUG_TEXT_MAX_SCALE); - dump(m_init.resolution); + + m_init.swapChain.flags |= _init.reset & kSwapChainFlagMask; + m_init.reset &= ~kSwapChainFlagMask; + m_init.reset &= ~BGFX_RESET_INTERNAL_FORCE; + m_init.swapChain.numBackBuffers = bx::clamp(_init.swapChain.numBackBuffers, 2, BGFX_CONFIG_MAX_BACK_BUFFERS); + m_init.swapChain.maxFrameLatency = bx::min(_init.swapChain.maxFrameLatency, BGFX_CONFIG_MAX_FRAME_LATENCY); + dump(m_init.swapChain, m_init.reset); bx::memCopy(&g_platformData, &m_init.platformData, sizeof(PlatformData) ); m_exit = false; m_flipped = true; m_debug = BGFX_DEBUG_NONE; + m_debugFrameBuffer = BGFX_INVALID_HANDLE; + m_debugTextScale = 1; m_frameTimeLast = bx::getHPCounter(); - m_flipAfterRender = !!(m_init.resolution.reset & BGFX_RESET_FLIP_AFTER_RENDER); + m_flipAfterRender = !!(m_init.reset & BGFX_RESET_FLIP_AFTER_RENDER); m_submit->create(_init.limits.minResourceCbSize, _init.limits.numDrawCalls, g_caps.limits.maxDrawCalls, _init.limits.numDrawCallPeakFrames); @@ -2568,7 +2513,7 @@ namespace bgfx dumpCaps(); - m_textVideoMemBlitter.init(m_init.resolution.debugTextScale); + m_textVideoMemBlitter.init(); m_clearQuad.init(); m_mipGen.init(); m_blitFallback.init(); @@ -2935,9 +2880,12 @@ namespace bgfx void Context::swap() { freeDynamicBuffers(); - m_submit->m_resolution = m_init.resolution; - m_init.resolution.reset &= ~BGFX_RESET_INTERNAL_FORCE; - m_submit->m_debug = m_debug; + m_submit->m_mainSwapChain = m_init.swapChain; + m_submit->m_reset = m_init.reset; + m_init.reset &= ~BGFX_RESET_INTERNAL_FORCE; + m_submit->m_debug = m_debug; + m_submit->m_debugFrameBuffer = m_debugFrameBuffer; + m_submit->m_debugTextScale = m_debugTextScale; m_submit->m_perfStats.numViews = 0; bx::memCopy(m_submit->m_viewRemap, m_viewRemap, sizeof(m_viewRemap) ); @@ -2981,8 +2929,8 @@ namespace bgfx { m_submit->m_textVideoMem->resize( m_render->m_textVideoMem->m_small - , m_init.resolution.width - , m_init.resolution.height + , m_init.swapChain.width + , m_init.swapChain.height ); } @@ -3987,22 +3935,7 @@ namespace bgfx if (window) { - void* nwh; - _cmdbuf.read(nwh); - - uint16_t width; - _cmdbuf.read(width); - - uint16_t height; - _cmdbuf.read(height); - - TextureFormat::Enum format; - _cmdbuf.read(format); - - TextureFormat::Enum depthFormat; - _cmdbuf.read(depthFormat); - - m_renderCtx->createFrameBuffer(handle, nwh, width, height, format, depthFormat); + m_renderCtx->createFrameBuffer(handle, readSwapChain(_cmdbuf) ); } else { @@ -4017,6 +3950,17 @@ namespace bgfx } break; + case CommandBuffer::ResizeFrameBuffer: + { + BGFX_PROFILER_SCOPE("ResizeFrameBuffer", kColorResource); + + FrameBufferHandle handle; + _cmdbuf.read(handle); + + m_renderCtx->resizeFrameBuffer(handle, readSwapChain(_cmdbuf) ); + } + break; + case CommandBuffer::DestroyFrameBuffer: { BGFX_PROFILER_SCOPE("DestroyFrameBuffer", kColorResource); @@ -4161,25 +4105,23 @@ namespace bgfx } PlatformData::PlatformData() - : ndt(NULL) - , nwh(NULL) - , context(NULL) + : context(NULL) , queue(NULL) - , backBuffer(NULL) - , backBufferDS(NULL) , type(NativeWindowHandleType::Default) { } - Resolution::Resolution() - : formatColor(TextureFormat::BGRA8) - , formatDepthStencil(TextureFormat::D24S8) - , width(1280) - , height(720) - , reset(BGFX_RESET_NONE) - , numBackBuffers(2) + SwapChain::SwapChain() + : nwh(NULL) + , ndt(NULL) + , width(0) + , height(0) + , flags(BGFX_SWAP_CHAIN_NONE) + , formatColor(TextureFormat::Count) + , formatDepthStencil(TextureFormat::Count) + , depth(BGFX_INVALID_HANDLE) + , numBackBuffers(0) , maxFrameLatency(0) - , debugTextScale(0) { } @@ -4206,9 +4148,15 @@ namespace bgfx , profile(BX_ENABLED(BGFX_CONFIG_DEBUG_ANNOTATION) ) , fallback(true) , videoDecode(false) + , reset(BGFX_RESET_NONE) , callback(NULL) , allocator(NULL) { + swapChain.width = 1280; + swapChain.height = 720; + swapChain.formatColor = TextureFormat::BGRA8; + swapChain.formatDepthStencil = TextureFormat::D24S8; + swapChain.numBackBuffers = 2; } void Attachment::init(TextureHandle _handle, Access::Enum _access, uint16_t _layer, uint16_t _numLayers, uint16_t _mip, uint8_t _resolve) @@ -4390,11 +4338,11 @@ namespace bgfx g_allocator = NULL; } - void reset(uint32_t _width, uint32_t _height, uint32_t _flags, TextureFormat::Enum _format) + void reset(uint32_t _flags, const SwapChain* _swapChain) { BGFX_CHECK_API_THREAD(); BX_ASSERT(0 == (_flags&BGFX_RESET_RESERVED_MASK), "Do not set reset reserved flags!"); - s_ctx->reset(_width, _height, _flags, _format); + s_ctx->reset(_flags, _swapChain); } Encoder* begin(bool _forceNewEncoder) @@ -5296,10 +5244,10 @@ namespace bgfx bx::free(g_allocator, mem); } - void setDebug(uint32_t _debug) + void setDebug(uint32_t _debug, FrameBufferHandle _handle, uint8_t _scale) { BGFX_CHECK_API_THREAD(); - s_ctx->setDebug(_debug); + s_ctx->setDebug(_debug, _handle, _scale); } void dbgTextClear(uint8_t _attr, bool _small) @@ -6192,8 +6140,8 @@ namespace bgfx { if (BackbufferRatio::Count != _ratio) { - _width = uint16_t(s_ctx->m_init.resolution.width); - _height = uint16_t(s_ctx->m_init.resolution.height); + _width = uint16_t(s_ctx->m_init.swapChain.width); + _height = uint16_t(s_ctx->m_init.swapChain.height); getTextureSizeFromRatio(_ratio, _width, _height); } @@ -6554,36 +6502,40 @@ namespace bgfx return s_ctx->createFrameBuffer(_num, _attachment, _destroyTextures); } - FrameBufferHandle createFrameBuffer(void* _nwh, uint16_t _width, uint16_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) + FrameBufferHandle createFrameBuffer(const SwapChain& _desc) { BGFX_CHECK_CAPS(BGFX_CAPS_SWAP_CHAIN, "Swap chain is not supported!"); - BX_WARN(_width > 0 && _height > 0 + BX_WARN(_desc.width > 0 && _desc.height > 0 , "Invalid frame buffer dimensions (width %d, height %d)." - , _width - , _height + , _desc.width + , _desc.height ); - BX_ASSERT(_format == TextureFormat::Count || bimg::isColor(bimg::TextureFormat::Enum(_format) ) + BX_ASSERT(_desc.formatColor == TextureFormat::Count || bimg::isColor(bimg::TextureFormat::Enum(_desc.formatColor) ) , "Invalid texture format for color (%s)." - , bimg::getName(bimg::TextureFormat::Enum(_format) ) + , bimg::getName(bimg::TextureFormat::Enum(_desc.formatColor) ) ); - BX_ASSERT(_depthFormat == TextureFormat::Count || bimg::isDepth(bimg::TextureFormat::Enum(_depthFormat) ) + BX_ASSERT(_desc.formatDepthStencil == TextureFormat::Count || bimg::isDepth(bimg::TextureFormat::Enum(_desc.formatDepthStencil) ) , "Invalid texture format for depth (%s)." - , bimg::getName(bimg::TextureFormat::Enum(_depthFormat) ) + , bimg::getName(bimg::TextureFormat::Enum(_desc.formatDepthStencil) ) ); - return s_ctx->createFrameBuffer( - _nwh - , bx::max(_width, 1) - , bx::max(_height, 1) - , _format - , _depthFormat + return s_ctx->createFrameBuffer(_desc); + } + + void updateSwapChain(FrameBufferHandle _handle, const SwapChain& _desc) + { + BGFX_CHECK_CAPS(BGFX_CAPS_SWAP_CHAIN, "Swap chain is not supported!"); + BX_WARN(_desc.width > 0 && _desc.height > 0 + , "Invalid frame buffer dimensions (width %d, height %d)." + , _desc.width + , _desc.height ); + s_ctx->updateSwapChain(_handle, _desc); } void setName(FrameBufferHandle _handle, const char* _name, int32_t _len) { s_ctx->setName(_handle, bx::StringView(_name, _len) ); } - TextureHandle getTexture(FrameBufferHandle _handle, uint8_t _attachment) { return s_ctx->getTexture(_handle, _attachment); @@ -6696,8 +6648,8 @@ namespace bgfx { BX_ASSERT(checkView(_id), "Invalid view id: %d", _id); - uint16_t width = uint16_t(s_ctx->m_init.resolution.width); - uint16_t height = uint16_t(s_ctx->m_init.resolution.height); + uint16_t width = uint16_t(s_ctx->m_init.swapChain.width); + uint16_t height = uint16_t(s_ctx->m_init.swapChain.height); getTextureSizeFromRatio(_ratio, width, height); setViewRect(_id, _x, _y, width, height); } @@ -7237,6 +7189,37 @@ static_assert(FLAGS_MASK_TEST(0 , BGFX_RESET_RESERVED_MASK ) ); +static_assert(BGFX_SWAP_CHAIN_FULLSCREEN == BGFX_RESET_FULLSCREEN); +static_assert(BGFX_SWAP_CHAIN_SRGB_BACKBUFFER == BGFX_RESET_SRGB_BACKBUFFER); +static_assert(BGFX_SWAP_CHAIN_HDR10 == BGFX_RESET_HDR10); +static_assert(BGFX_SWAP_CHAIN_HIDPI == BGFX_RESET_HIDPI); +static_assert(BGFX_SWAP_CHAIN_TRANSPARENT_BACKBUFFER == BGFX_RESET_TRANSPARENT_BACKBUFFER); +static_assert(BGFX_SWAP_CHAIN_MSAA_X2 == BGFX_RESET_MSAA_X2); +static_assert(BGFX_SWAP_CHAIN_MSAA_X4 == BGFX_RESET_MSAA_X4); +static_assert(BGFX_SWAP_CHAIN_MSAA_X8 == BGFX_RESET_MSAA_X8); +static_assert(BGFX_SWAP_CHAIN_MSAA_X16 == BGFX_RESET_MSAA_X16); +static_assert(BGFX_SWAP_CHAIN_MSAA_SHIFT == BGFX_RESET_MSAA_SHIFT); +static_assert(BGFX_SWAP_CHAIN_MSAA_MASK == BGFX_RESET_MSAA_MASK); + +static_assert(FLAGS_MASK_TEST(0 + | BGFX_SWAP_CHAIN_FULLSCREEN + | BGFX_SWAP_CHAIN_MSAA_MASK + | BGFX_SWAP_CHAIN_SRGB_BACKBUFFER + | BGFX_SWAP_CHAIN_HDR10 + | BGFX_SWAP_CHAIN_HIDPI + | BGFX_SWAP_CHAIN_TRANSPARENT_BACKBUFFER + , ~(0 + | BGFX_RESET_VSYNC + | BGFX_RESET_MAXANISOTROPY + | BGFX_RESET_CAPTURE + | BGFX_RESET_FLUSH_AFTER_RENDER + | BGFX_RESET_FLIP_AFTER_RENDER + | BGFX_RESET_DEPTH_CLAMP + | BGFX_RESET_SUSPEND + | BGFX_RESET_RESERVED_MASK + ) + ) ); + static_assert(FLAGS_MASK_TEST(0 | BGFX_STATE_INTERNAL_SCISSOR | BGFX_STATE_INTERNAL_OCCLUSION_QUERY diff --git a/src/bgfx.idl.inl b/src/bgfx.idl.inl index 5e861eb3f..6f3fdf5d8 100644 --- a/src/bgfx.idl.inl +++ b/src/bgfx.idl.inl @@ -184,9 +184,9 @@ BGFX_C_API void bgfx_shutdown(void) bgfx::shutdown(); } -BGFX_C_API void bgfx_reset(uint32_t _width, uint32_t _height, uint32_t _flags, bgfx_texture_format_t _format) +BGFX_C_API void bgfx_reset(uint32_t _flags, const bgfx_swap_chain_t* _swapChain) { - bgfx::reset(_width, _height, _flags, (bgfx::TextureFormat::Enum)_format); + bgfx::reset(_flags, (const bgfx::SwapChain*)_swapChain); } BGFX_C_API uint32_t bgfx_frame(uint8_t _flags) @@ -229,9 +229,10 @@ BGFX_C_API const bgfx_memory_t* bgfx_make_ref_release(const void* _data, uint32_ return (const bgfx_memory_t*)bgfx::makeRef(_data, _size, (bgfx::ReleaseFn)_releaseFn, _userData); } -BGFX_C_API void bgfx_set_debug(uint32_t _debug) +BGFX_C_API void bgfx_set_debug(uint32_t _debug, bgfx_frame_buffer_handle_t _handle, uint8_t _scale) { - bgfx::setDebug(_debug); + union { bgfx_frame_buffer_handle_t c; bgfx::FrameBufferHandle cpp; } handle = { _handle }; + bgfx::setDebug(_debug, handle.cpp, _scale); } BGFX_C_API void bgfx_dbg_text_clear(uint8_t _attr, bool _small) @@ -601,13 +602,21 @@ BGFX_C_API bgfx_frame_buffer_handle_t bgfx_create_frame_buffer_from_attachment(u return handle_ret.c; } -BGFX_C_API bgfx_frame_buffer_handle_t bgfx_create_frame_buffer_from_nwh(void* _nwh, uint16_t _width, uint16_t _height, bgfx_texture_format_t _format, bgfx_texture_format_t _depthFormat) +BGFX_C_API bgfx_frame_buffer_handle_t bgfx_create_frame_buffer_from_swap_chain(const bgfx_swap_chain_t* _desc) { + const bgfx::SwapChain& desc = *(const bgfx::SwapChain*)_desc; union { bgfx_frame_buffer_handle_t c; bgfx::FrameBufferHandle cpp; } handle_ret; - handle_ret.cpp = bgfx::createFrameBuffer(_nwh, _width, _height, (bgfx::TextureFormat::Enum)_format, (bgfx::TextureFormat::Enum)_depthFormat); + handle_ret.cpp = bgfx::createFrameBuffer(desc); return handle_ret.c; } +BGFX_C_API void bgfx_update_swap_chain(bgfx_frame_buffer_handle_t _handle, const bgfx_swap_chain_t* _desc) +{ + union { bgfx_frame_buffer_handle_t c; bgfx::FrameBufferHandle cpp; } handle = { _handle }; + const bgfx::SwapChain& desc = *(const bgfx::SwapChain*)_desc; + bgfx::updateSwapChain(handle.cpp, desc); +} + BGFX_C_API void bgfx_set_frame_buffer_name(bgfx_frame_buffer_handle_t _handle, const char* _name, int32_t _len) { union { bgfx_frame_buffer_handle_t c; bgfx::FrameBufferHandle cpp; } handle = { _handle }; @@ -1096,29 +1105,11 @@ BGFX_C_API bgfx_render_frame_t bgfx_render_frame(int32_t _msecs) return (bgfx_render_frame_t)bgfx::renderFrame(_msecs); } -BGFX_C_API void bgfx_set_platform_data(const bgfx_platform_data_t * _data) -{ - const bgfx::PlatformData & data = *(const bgfx::PlatformData *)_data; - bgfx::setPlatformData(data); -} - BGFX_C_API const bgfx_internal_data_t* bgfx_get_internal_data(void) { return (const bgfx_internal_data_t*)bgfx::getInternalData(); } -BGFX_C_API uintptr_t bgfx_override_internal_texture_ptr(bgfx_texture_handle_t _handle, uintptr_t _ptr, uint16_t _layerIndex) -{ - union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } handle = { _handle }; - return bgfx::overrideInternal(handle.cpp, _ptr, _layerIndex); -} - -BGFX_C_API uintptr_t bgfx_override_internal_texture(bgfx_texture_handle_t _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, bgfx_texture_format_t _format, uint64_t _flags) -{ - union { bgfx_texture_handle_t c; bgfx::TextureHandle cpp; } handle = { _handle }; - return bgfx::overrideInternal(handle.cpp, _width, _height, _numMips, (bgfx::TextureFormat::Enum)_format, _flags); -} - BGFX_C_API void bgfx_set_marker(const char* _name, int32_t _len) { bgfx::setMarker(_name, _len); @@ -1518,7 +1509,8 @@ BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version) bgfx_create_frame_buffer_scaled, bgfx_create_frame_buffer_from_handles, bgfx_create_frame_buffer_from_attachment, - bgfx_create_frame_buffer_from_nwh, + bgfx_create_frame_buffer_from_swap_chain, + bgfx_update_swap_chain, bgfx_set_frame_buffer_name, bgfx_get_texture, bgfx_destroy_frame_buffer, @@ -1595,10 +1587,7 @@ BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version) bgfx_encoder_blit_from_buffer, bgfx_request_screen_shot, bgfx_render_frame, - bgfx_set_platform_data, bgfx_get_internal_data, - bgfx_override_internal_texture_ptr, - bgfx_override_internal_texture, bgfx_set_marker, bgfx_set_state, bgfx_set_condition, diff --git a/src/bgfx_p.h b/src/bgfx_p.h index b661a34c3..3bdec31e5 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -261,6 +261,15 @@ namespace bgfx static constexpr uint32_t kVideoDecoderInitMagic = BX_MAKEFOURCC('V', 'D', 'I', 0x0); static constexpr uint32_t kVideoDecoderFrameMagic = BX_MAKEFOURCC('V', 'D', 'F', 0x0); + static constexpr uint32_t kSwapChainFlagMask = 0 + | BGFX_SWAP_CHAIN_FULLSCREEN + | BGFX_SWAP_CHAIN_MSAA_MASK + | BGFX_SWAP_CHAIN_SRGB_BACKBUFFER + | BGFX_SWAP_CHAIN_HDR10 + | BGFX_SWAP_CHAIN_HIDPI + | BGFX_SWAP_CHAIN_TRANSPARENT_BACKBUFFER + ; + // Palette: // https://colorkit.co/color-palette-generator/a8e6cf-dcedc1-ffd3b6-76b4bd-bdeaee-8874a3-ff0000-ff8b94/ static constexpr uint32_t kColorFrame = 0xa8'e6'cf'ff; @@ -274,7 +283,6 @@ namespace bgfx extern InternalData g_internalData; extern PlatformData g_platformData; - extern bool g_platformDataChangedSinceReset; extern void isFrameBufferValid(uint8_t _num, const Attachment* _attachment, bx::Error* _err); extern void isIdentifierValid(const bx::StringView& _name, bx::Error* _err); @@ -716,7 +724,7 @@ namespace bgfx void dump(const VertexLayout& _layout); /// Dump resolution and reset info into debug output. - void dump(const Resolution& _resolution); + void dump(const SwapChain& _swapChain, uint32_t _reset); struct TextVideoMem { @@ -824,7 +832,7 @@ namespace bgfx struct TextVideoMemBlitter { - void init(uint8_t scale); + void init(); void shutdown(); TextureHandle m_texture; @@ -832,20 +840,19 @@ namespace bgfx TransientIndexBuffer* m_ib; VertexLayout m_layout; ProgramHandle m_program; - uint8_t m_scale; uintptr_t m_usedData; }; struct RendererContextI; - extern void dbgTextSubmit(RendererContextI* _renderCtx, TextVideoMemBlitter& _blitter, const TextVideoMem& _mem); + extern void dbgTextSubmit(RendererContextI* _renderCtx, TextVideoMemBlitter& _blitter, const TextVideoMem& _mem, FrameBufferHandle _handle, uint8_t _scale); - inline void dbgTextSubmit(RendererContextI* _renderCtx, TextVideoMemBlitter& _blitter, const TextVideoMem* _mem) + inline void dbgTextSubmit(RendererContextI* _renderCtx, TextVideoMemBlitter& _blitter, const TextVideoMem* _mem, FrameBufferHandle _handle, uint8_t _scale) { if (NULL != _mem) { - dbgTextSubmit(_renderCtx, _blitter, *_mem); + dbgTextSubmit(_renderCtx, _blitter, *_mem, _handle, _scale); } } @@ -1102,6 +1109,7 @@ namespace bgfx ClearTexture, ResizeTexture, CreateFrameBuffer, + ResizeFrameBuffer, CreateUniform, UpdateViewName, InvalidateOcclusionQuery, @@ -2942,6 +2950,8 @@ namespace bgfx void* m_nwh; } un; + SwapChain m_swapChain; + bool m_window; }; @@ -3606,9 +3616,13 @@ namespace bgfx TransientIndexBuffer* m_transientIb; TransientVertexBuffer* m_transientVb; - Resolution m_resolution; + SwapChain m_mainSwapChain; + uint32_t m_reset; uint32_t m_debug; + FrameBufferHandle m_debugFrameBuffer; + uint8_t m_debugTextScale; + ScreenShot m_screenShot[BGFX_CONFIG_MAX_SCREENSHOTS]; uint8_t m_numScreenShots; @@ -3733,7 +3747,7 @@ namespace bgfx m_numSubmitted = 0; m_numDropped = 0; - m_bindHashMap.reset(); + m_bindHashMap.clear(); m_bindLlastIdx = 0; m_bindEmptyIdx = UINT32_MAX; m_bindDirty = true; @@ -4850,11 +4864,33 @@ namespace bgfx virtual void readTexture(TextureHandle _handle, void* _data, uint16_t _layer, uint8_t _mip) = 0; virtual void readBuffer(Handle _handle, void* _data, uint32_t _offset, uint32_t _size) = 0; virtual void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips, uint16_t _numLayers) = 0; - virtual void overrideInternal(TextureHandle _handle, uintptr_t _ptr, uint16_t _layerIndex) = 0; virtual uintptr_t getInternal(TextureHandle _handle) = 0; virtual void destroyTexture(TextureHandle _handle) = 0; virtual void createFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const Attachment* _attachment) = 0; - virtual void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) = 0; + virtual void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) + { + BX_UNUSED(_handle, _nwh, _width, _height, _format, _depthFormat); + BX_ASSERT(false, "Not implemented!"); + } + + virtual void createFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) + { + createFrameBuffer( + _handle + , _desc.nwh + , _desc.width + , _desc.height + , _desc.formatColor + , _desc.formatDepthStencil + ); + } + + virtual void resizeFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) + { + destroyFrameBuffer(_handle); + createFrameBuffer(_handle, _desc); + } + virtual void destroyFrameBuffer(FrameBufferHandle _handle) = 0; virtual void createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) = 0; virtual void destroyUniform(UniformHandle _handle) = 0; @@ -4865,7 +4901,7 @@ namespace bgfx virtual void setMarker(const char* _name, uint16_t _len) = 0; virtual void setName(Handle _handle, const char* _name, uint16_t _len) = 0; virtual void submit(Frame* _render, const ClearQuad& _clearQuad, const MipGen& _mipGen, TextVideoMemBlitter& _textVideoMemBlitter) = 0; - virtual void dbgTextRenderBegin(TextVideoMemBlitter& _blitter) = 0; + virtual void dbgTextRenderBegin(TextVideoMemBlitter& _blitter, FrameBufferHandle _handle) = 0; virtual void dbgTextRender(TextVideoMemBlitter& _blitter, uint32_t _numIndices) = 0; virtual void dbgTextRenderEnd(TextVideoMemBlitter& _blitter) = 0; }; @@ -4952,75 +4988,90 @@ namespace bgfx return cmdbuf; } - BGFX_API_FUNC(void reset(uint32_t _width, uint32_t _height, uint32_t _flags, TextureFormat::Enum _formatColor) ) + BGFX_API_FUNC(void reset(uint32_t _flags, const SwapChain* _swapChain) ) { BGFX_MUTEX_SCOPE(m_resourceApiLock); - BX_ASSERT(false - || !m_headless - || 0 == _width - || 0 == _height - , "Running in headless mode, resolution of non-existing backbuffer can't be larger than 0x0!" + BX_ASSERT(NULL == _swapChain || !m_headless + , "bgfx::init created no main swap chain, so `_swapChain` must be NULL." ); - const TextureFormat::Enum formatColor = TextureFormat::Count != _formatColor - ? _formatColor - : m_init.resolution.formatColor - ; - - BX_ASSERT(0 != (g_caps.formats[formatColor] & BGFX_CAPS_FORMAT_TEXTURE_BACKBUFFER) - , "Format %s can't be used for back buffer!" - , getName(formatColor) + BX_WARN(0 == (_flags & kSwapChainFlagMask) + , "Per-surface flags passed to `reset` are ignored. They belong on `SwapChain::flags`." ); - if (!g_platformDataChangedSinceReset - && m_init.resolution.formatColor == formatColor - && m_init.resolution.width == _width - && m_init.resolution.height == _height - && m_init.resolution.reset == _flags - ) + const uint32_t resetFlags = _flags & ~kSwapChainFlagMask; + + SwapChain swapChain = m_init.swapChain; + + if (NULL != _swapChain + && !m_headless) + { + checkSwapChainDepth(*_swapChain); + + swapChain = *_swapChain; + + if (NULL == swapChain.nwh) + { + swapChain.nwh = m_init.swapChain.nwh; + } + + if (NULL == swapChain.ndt) + { + swapChain.ndt = m_init.swapChain.ndt; + } + + if (TextureFormat::Count == swapChain.formatColor) + { + swapChain.formatColor = m_init.swapChain.formatColor; + } + + if (TextureFormat::Count == swapChain.formatDepthStencil) + { + swapChain.formatDepthStencil = m_init.swapChain.formatDepthStencil; + } + + if (0 == swapChain.numBackBuffers) + { + swapChain.numBackBuffers = m_init.swapChain.numBackBuffers; + } + + if (0 == swapChain.maxFrameLatency) + { + swapChain.maxFrameLatency = m_init.swapChain.maxFrameLatency; + } + + BX_ASSERT(0 != (g_caps.formats[swapChain.formatColor] & BGFX_CAPS_FORMAT_TEXTURE_BACKBUFFER) + , "Format %s can't be used for back buffer!" + , getName(swapChain.formatColor) + ); + + BX_WARN(g_caps.limits.maxTextureSize >= swapChain.width + && g_caps.limits.maxTextureSize >= swapChain.height + , "Frame buffer resolution width or height can't be larger than limits.maxTextureSize %d (width %d, height %d)." + , g_caps.limits.maxTextureSize + , swapChain.width + , swapChain.height + ); + + swapChain.flags = checkSwapChainFlags(swapChain.flags & kSwapChainFlagMask); + swapChain.width = bx::clamp(swapChain.width, 1u, g_caps.limits.maxTextureSize); + swapChain.height = bx::clamp(swapChain.height, 1u, g_caps.limits.maxTextureSize); + } + + if (m_init.reset == resetFlags + && 0 == bx::memCmp(&swapChain, &m_init.swapChain, sizeof(SwapChain) ) ) { // Nothing changed, ignore request. return; } - const uint32_t maskFlags = ~(0 - | (0 != (g_caps.supported & BGFX_CAPS_TRANSPARENT_BACKBUFFER) ? 0 : BGFX_RESET_TRANSPARENT_BACKBUFFER) - | (0 != (g_caps.supported & BGFX_CAPS_HDR10) ? 0 : BGFX_RESET_HDR10) - | (0 != (g_caps.supported & BGFX_CAPS_HIDPI) ? 0 : BGFX_RESET_HIDPI) - ); - const uint32_t oldFlags = _flags; - _flags &= maskFlags; + m_init.swapChain = swapChain; + m_init.reset = resetFlags; -#define WARN_RESET_CAPS_FLAGS(_name) \ - BX_WARN( (oldFlags&(BGFX_RESET_##_name) ) == (_flags&(BGFX_RESET_##_name) ) \ - , "Reset flag `BGFX_RESET_" #_name "` will be ignored, because `BGFX_CAPS_" #_name "` is not supported." \ - ) - WARN_RESET_CAPS_FLAGS(TRANSPARENT_BACKBUFFER); - WARN_RESET_CAPS_FLAGS(HDR10); - WARN_RESET_CAPS_FLAGS(HIDPI); + dump(m_init.swapChain, m_init.reset); -#undef WARN_RESET_CAPS_FLAGS - BX_UNUSED(oldFlags); - - BX_WARN(g_caps.limits.maxTextureSize >= _width - && g_caps.limits.maxTextureSize >= _height - , "Frame buffer resolution width or height can't be larger than limits.maxTextureSize %d (width %d, height %d)." - , g_caps.limits.maxTextureSize - , _width - , _height - ); - m_init.resolution.formatColor = formatColor; - m_init.resolution.width = bx::clamp(_width, 1u, g_caps.limits.maxTextureSize); - m_init.resolution.height = bx::clamp(_height, 1u, g_caps.limits.maxTextureSize); - m_init.resolution.reset = 0 - | _flags - | (g_platformDataChangedSinceReset ? BGFX_RESET_INTERNAL_FORCE : 0) - ; - dump(m_init.resolution); - g_platformDataChangedSinceReset = false; - - m_flipAfterRender = !!(_flags & BGFX_RESET_FLIP_AFTER_RENDER); + m_flipAfterRender = !!(resetFlags & BGFX_RESET_FLIP_AFTER_RENDER); for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) { @@ -5035,19 +5086,38 @@ namespace bgfx { TextureHandle handle = { textureIdx }; resizeTexture(handle - , uint16_t(m_init.resolution.width) - , uint16_t(m_init.resolution.height) + , uint16_t(m_init.swapChain.width) + , uint16_t(m_init.swapChain.height) , ref.m_numMips , ref.m_numLayers ); - m_init.resolution.reset |= BGFX_RESET_INTERNAL_FORCE; + m_init.reset |= BGFX_RESET_INTERNAL_FORCE; } } } - BGFX_API_FUNC(void setDebug(uint32_t _debug) ) + BGFX_API_FUNC(void setDebug(uint32_t _debug, FrameBufferHandle _handle, uint8_t _scale) ) { - m_debug = _debug; + BGFX_CHECK_HANDLE_INVALID_OK("setDebug", m_frameBufferHandle, _handle); + + m_debug = _debug; + m_debugFrameBuffer = _handle; + m_debugTextScale = bx::clamp(_scale, 1, BGFX_CONFIG_DEBUG_TEXT_MAX_SCALE); + } + + void getDebugFrameBufferSize(uint16_t& _width, uint16_t& _height) const + { + if (isValid(m_debugFrameBuffer) ) + { + const FrameBufferRef& fbr = m_frameBufferRef[m_debugFrameBuffer.idx]; + _width = fbr.m_width; + _height = fbr.m_height; + } + else + { + _width = uint16_t(m_init.swapChain.width); + _height = uint16_t(m_init.swapChain.height); + } } BGFX_API_FUNC(void dbgTextClear(uint8_t _attr, bool _small) ) @@ -5056,11 +5126,14 @@ namespace bgfx if (BX_ENABLED(BGFX_CONFIG_DEBUG_TEXT) ) { - const uint8_t debugTextScale = m_init.resolution.debugTextScale; + uint16_t width; + uint16_t height; + getDebugFrameBufferSize(width, height); + m_submit->m_textVideoMem->resize( _small - , (uint16_t)m_init.resolution.width / debugTextScale - , (uint16_t)m_init.resolution.height / debugTextScale + , width / m_debugTextScale + , height / m_debugTextScale ); m_submit->m_textVideoMem->clear(_attr); } @@ -5091,7 +5164,7 @@ namespace bgfx BGFX_MUTEX_SCOPE(m_resourceApiLock); Stats& stats = m_submit->m_perfStats; - const Resolution& resolution = m_submit->m_resolution; + const SwapChain& resolution = m_submit->m_mainSwapChain; stats.width = uint16_t(resolution.width); stats.height = uint16_t(resolution.height); stats.textWidth = 0; @@ -6835,34 +6908,166 @@ namespace bgfx return handle; } - BGFX_API_FUNC(FrameBufferHandle createFrameBuffer(void* _nwh, uint16_t _width, uint16_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) ) + static void writeSwapChain(CommandBuffer& _cmdbuf, const FrameBufferRef& _fbr) + { + _cmdbuf.write(_fbr.m_swapChain); + } + + SwapChain readSwapChain(CommandBuffer& _cmdbuf) + { + SwapChain desc; + _cmdbuf.read(desc); + + const SwapChain& main = m_render->m_mainSwapChain; + + if (NULL == desc.ndt) + { + desc.ndt = main.ndt; + } + + if (TextureFormat::Count == desc.formatColor) + { + desc.formatColor = main.formatColor; + } + + if (TextureFormat::Count == desc.formatDepthStencil) + { + desc.formatDepthStencil = main.formatDepthStencil; + } + + if (0 == desc.numBackBuffers) + { + desc.numBackBuffers = main.numBackBuffers; + } + + if (0 == desc.maxFrameLatency) + { + desc.maxFrameLatency = main.maxFrameLatency; + } + + return desc; + } + + static uint32_t checkSwapChainFlags(uint32_t _flags) + { + const uint32_t maskFlags = ~(0 + | (0 != (g_caps.supported & BGFX_CAPS_TRANSPARENT_BACKBUFFER) ? 0 : BGFX_SWAP_CHAIN_TRANSPARENT_BACKBUFFER) + | (0 != (g_caps.supported & BGFX_CAPS_HDR10) ? 0 : BGFX_SWAP_CHAIN_HDR10) + | (0 != (g_caps.supported & BGFX_CAPS_HIDPI) ? 0 : BGFX_SWAP_CHAIN_HIDPI) + ); + + const uint32_t flags = _flags & maskFlags; + +#define WARN_SWAP_CHAIN_CAPS_FLAGS(_name) \ + BX_WARN( (_flags&(BGFX_SWAP_CHAIN_##_name) ) == (flags&(BGFX_SWAP_CHAIN_##_name) ) \ + , "Swap chain flag `BGFX_SWAP_CHAIN_" #_name "` will be ignored, because " \ + "`BGFX_CAPS_" #_name "` is not supported." \ + ) + WARN_SWAP_CHAIN_CAPS_FLAGS(TRANSPARENT_BACKBUFFER); + WARN_SWAP_CHAIN_CAPS_FLAGS(HDR10); + WARN_SWAP_CHAIN_CAPS_FLAGS(HIDPI); + +#undef WARN_SWAP_CHAIN_CAPS_FLAGS + + return flags; + } + + void checkSwapChainDepth(const SwapChain& _desc) + { + if (!isValid(_desc.depth) ) + { + return; + } + + BGFX_CHECK_HANDLE("SwapChain::depth", m_textureHandle, _desc.depth); + + const TextureRef& ref = m_textureRef[_desc.depth.idx]; + + BX_ASSERT(ref.isRt() + , "SwapChain::depth texture must be created with BGFX_TEXTURE_RT." + ); + BX_ASSERT(ref.isDepth() + , "SwapChain::depth texture format (%s) is not a depth format." + , getName(TextureFormat::Enum(ref.m_format) ) + ); + BX_ASSERT(BackbufferRatio::Count == ref.m_bbRatio + , "SwapChain::depth cannot be a BackbufferRatio texture, because ratio " + "resolves against the window bgfx was initialized with, not this one." + ); + BX_ASSERT(ref.m_width == _desc.width && ref.m_height == _desc.height + , "SwapChain::depth is %dx%d, but the swap chain is %dx%d." + , ref.m_width + , ref.m_height + , _desc.width + , _desc.height + ); + + const uint32_t msaa = (_desc.flags & BGFX_SWAP_CHAIN_MSAA_MASK) >> BGFX_SWAP_CHAIN_MSAA_SHIFT; + const uint32_t numSamples = 0 == msaa ? 1 : 1<(_desc.width, 1) ); + fbr.m_height = uint16_t(bx::max(_desc.height, 1) ); + fbr.m_window = true; + fbr.un.m_nwh = _desc.nwh; + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateFrameBuffer); cmdbuf.write(handle); cmdbuf.write(true); - cmdbuf.write(_nwh); - cmdbuf.write(_width); - cmdbuf.write(_height); - cmdbuf.write(_format); - cmdbuf.write(_depthFormat); - - FrameBufferRef& fbr = m_frameBufferRef[handle.idx]; - fbr.m_width = _width; - fbr.m_height = _height; - fbr.m_window = true; - fbr.un.m_nwh = _nwh; + writeSwapChain(cmdbuf, fbr); } return handle; } + BGFX_API_FUNC(void updateSwapChain(FrameBufferHandle _handle, const SwapChain& _desc) ) + { + BGFX_MUTEX_SCOPE(m_resourceApiLock); + + BGFX_CHECK_HANDLE("updateSwapChain", m_frameBufferHandle, _handle); + + checkSwapChainDepth(_desc); + + FrameBufferRef& fbr = m_frameBufferRef[_handle.idx]; + + BX_ASSERT(fbr.m_window, "Frame buffer handle %d is not a window frame buffer.", _handle.idx); + if (!fbr.m_window) + { + return; + } + + fbr.m_swapChain = _desc; + fbr.m_swapChain.flags = checkSwapChainFlags(_desc.flags & kSwapChainFlagMask); + fbr.m_width = uint16_t(bx::max(_desc.width, 1) ); + fbr.m_height = uint16_t(bx::max(_desc.height, 1) ); + fbr.un.m_nwh = _desc.nwh; + + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::ResizeFrameBuffer); + cmdbuf.write(_handle); + writeSwapChain(cmdbuf, fbr); + } + BGFX_API_FUNC(void setName(FrameBufferHandle _handle, const bx::StringView& _name) ) { BGFX_MUTEX_SCOPE(m_resourceApiLock); @@ -7445,6 +7650,8 @@ namespace bgfx int64_t m_frameTimeLast; uint32_t m_frames; uint32_t m_debug; + FrameBufferHandle m_debugFrameBuffer; + uint8_t m_debugTextScale; int64_t m_rtMemoryUsed; int64_t m_textureMemoryUsed; diff --git a/src/config.h b/src/config.h index 27922a491..1f65d7c1c 100644 --- a/src/config.h +++ b/src/config.h @@ -602,14 +602,14 @@ static_assert(BGFX_CONFIG_MAX_VERTEX_STREAMS < 32, "Must be less than 32!"); #endif // BGFX_CONFIG_DEFAULT_MAX_ENCODERS /// Maximum number of back buffers for swap chain. Default is 4. -/// The actual number used is specified via bgfx::Resolution::numBackBuffers. +/// The actual number used is specified via bgfx::SwapChain::numBackBuffers. #ifndef BGFX_CONFIG_MAX_BACK_BUFFERS # define BGFX_CONFIG_MAX_BACK_BUFFERS 4 #endif // BGFX_CONFIG_MAX_BACK_BUFFERS /// Maximum frame latency (number of frames that can be queued ahead). /// Default is 3. The actual value is specified via -/// bgfx::Resolution::maxFrameLatency. +/// bgfx::SwapChain::maxFrameLatency. #ifndef BGFX_CONFIG_MAX_FRAME_LATENCY # define BGFX_CONFIG_MAX_FRAME_LATENCY 3 #endif // BGFX_CONFIG_MAX_FRAME_LATENCY diff --git a/src/dxgi.cpp b/src/dxgi.cpp index da3680ffc..98644a14f 100644 --- a/src/dxgi.cpp +++ b/src/dxgi.cpp @@ -466,7 +466,7 @@ namespace bgfx DX_RELEASE_I(dxgiDevice); } - HRESULT Dxgi::createSwapChain(IUnknown* _device, const SwapChainDesc& _scd, SwapChainI** _swapChain) + HRESULT Dxgi::createSwapChain(IUnknown* _device, const DxgiSwapChainDesc& _scd, SwapChainI** _swapChain) { HRESULT hr = S_OK; @@ -642,7 +642,7 @@ namespace bgfx return S_OK; } - HRESULT Dxgi::removeSwapChain(const SwapChainDesc& _scd) + HRESULT Dxgi::removeSwapChain(const DxgiSwapChainDesc& _scd) { #if BX_PLATFORM_WINRT IInspectable* nativeWindow = reinterpret_cast(_scd.nwh); @@ -653,7 +653,7 @@ namespace bgfx #endif // BX_PLATFORM_WINRT } - void Dxgi::updateHdr10(SwapChainI* _swapChain, const SwapChainDesc& _scd) + void Dxgi::updateHdr10(SwapChainI* _swapChain, const DxgiSwapChainDesc& _scd) { #if BX_PLATFORM_WINDOWS ::IDXGISwapChain4* swapChain4; @@ -727,7 +727,7 @@ namespace bgfx #endif // BX_PLATFORM_WINDOWS } - HRESULT Dxgi::resizeBuffers(SwapChainI* _swapChain, const SwapChainDesc& _scd, const uint32_t* _nodeMask, IUnknown* const* _presentQueue) + HRESULT Dxgi::resizeBuffers(SwapChainI* _swapChain, const DxgiSwapChainDesc& _scd, const uint32_t* _nodeMask, IUnknown* const* _presentQueue) { HRESULT hr; @@ -746,10 +746,10 @@ namespace bgfx BX_TRACE("Allow tearing is %ssupported.", allowTearing ? "" : "not "); scdFlags |= allowTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; - scdFlags |= false - || _scd.swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL - || _scd.swapEffect == DXGI_SWAP_EFFECT_FLIP_DISCARD - ? 0 // DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT + scdFlags |= (_scd.waitable + && (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL == _scd.swapEffect + || DXGI_SWAP_EFFECT_FLIP_DISCARD == _scd.swapEffect) ) + ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT : 0 ; diff --git a/src/dxgi.h b/src/dxgi.h index 26864e6f9..0d1aa7c74 100644 --- a/src/dxgi.h +++ b/src/dxgi.h @@ -28,7 +28,7 @@ namespace bgfx typedef HRESULT (WINAPI* PFN_GET_DEBUG_INTERFACE)(REFIID _riid, void** _debug); typedef HRESULT (WINAPI* PFN_GET_DEBUG_INTERFACE1)(UINT _flags, REFIID _riid, void** _debug); - struct SwapChainDesc + struct DxgiSwapChainDesc { uint32_t width; uint32_t height; @@ -87,16 +87,16 @@ namespace bgfx void update(IUnknown* _device); /// - HRESULT createSwapChain(IUnknown* _device, const SwapChainDesc& _scd, SwapChainI** _swapChain); + HRESULT createSwapChain(IUnknown* _device, const DxgiSwapChainDesc& _scd, SwapChainI** _swapChain); /// - HRESULT removeSwapChain(const SwapChainDesc& _scd); + HRESULT removeSwapChain(const DxgiSwapChainDesc& _scd); /// - void updateHdr10(SwapChainI* _swapChain, const SwapChainDesc& _scd); + void updateHdr10(SwapChainI* _swapChain, const DxgiSwapChainDesc& _scd); /// - HRESULT resizeBuffers(SwapChainI* _swapChain, const SwapChainDesc& _scd, const uint32_t* _nodeMask = NULL, IUnknown* const* _presentQueue = NULL); + HRESULT resizeBuffers(SwapChainI* _swapChain, const DxgiSwapChainDesc& _scd, const uint32_t* _nodeMask = NULL, IUnknown* const* _presentQueue = NULL); /// void trim(); diff --git a/src/glcontext_egl.cpp b/src/glcontext_egl.cpp index 907476fbb..80844c1f7 100644 --- a/src/glcontext_egl.cpp +++ b/src/glcontext_egl.cpp @@ -245,8 +245,10 @@ WL_EGL_IMPORT static EGL_DISPMANX_WINDOW_T s_dispmanWindow; # endif // BX_PLATFORM_RPI - void GlContext::create(const Resolution& _resolution) + void GlContext::create(const SwapChain& _swapChain, uint32_t _reset) { + m_nwh = _swapChain.nwh; + # if BX_PLATFORM_RPI bcm_host_init(); # endif // BX_PLATFORM_RPI @@ -256,15 +258,16 @@ WL_EGL_IMPORT if (m_ownsContext) { + void* ndtRaw = _swapChain.ndt; # if BX_PLATFORM_RPI - g_platformData.ndt = EGL_DEFAULT_DISPLAY; + ndtRaw = EGL_DEFAULT_DISPLAY; # endif // BX_PLATFORM_RPI - EGLNativeDisplayType ndt = (EGLNativeDisplayType)g_platformData.ndt; - EGLNativeWindowType nwh = (EGLNativeWindowType )g_platformData.nwh; + EGLNativeDisplayType ndt = (EGLNativeDisplayType)ndtRaw; + EGLNativeWindowType nwh = (EGLNativeWindowType )m_nwh; # if BX_PLATFORM_WINDOWS - if (NULL == g_platformData.ndt + if (NULL == ndtRaw && NULL != nwh) { m_hdc = GetDC( (HWND)nwh); @@ -312,13 +315,13 @@ WL_EGL_IMPORT : BGFX_CONFIG_RENDERER_OPENGLES ; - const uint32_t msaa = (_resolution.reset & BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + const uint32_t msaa = (_swapChain.flags & BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT; uint32_t msaaSamples = 0 == msaa ? 0 : 1<( (uintptr_t) g_platformData.context); if (context > 0) { @@ -98,16 +98,16 @@ namespace bgfx { namespace gl } else { - m_primary = createSwapChain( (void*)canvas, _resolution.width, _resolution.height); + m_primary = createSwapChain( (void*)canvas, _swapChain.width, _swapChain.height); } - if (0 != _resolution.width - && 0 != _resolution.height) + if (0 != _swapChain.width + && 0 != _swapChain.height) { EMSCRIPTEN_CHECK(emscripten_set_canvas_element_size( canvas - , _resolution.width - , _resolution.height + , _swapChain.width + , _swapChain.height ) ); } @@ -128,7 +128,7 @@ namespace bgfx { namespace gl } } - void GlContext::resize(const Resolution& _resolution) + void GlContext::resize(const SwapChain& _swapChain, uint32_t _reset) { if (m_primary == NULL) { @@ -137,8 +137,8 @@ namespace bgfx { namespace gl EMSCRIPTEN_CHECK(emscripten_set_canvas_element_size( m_primary->m_canvas - , _resolution.width - , _resolution.height + , _swapChain.width + , _swapChain.height ) ); } diff --git a/src/glcontext_html5.h b/src/glcontext_html5.h index b5de2380c..c3a7cb21b 100644 --- a/src/glcontext_html5.h +++ b/src/glcontext_html5.h @@ -21,9 +21,9 @@ namespace bgfx { namespace gl { } - void create(const Resolution& _resolution); + void create(const SwapChain& _swapChain, uint32_t _reset); void destroy(); - void resize(const Resolution& _resolution); + void resize(const SwapChain& _swapChain, uint32_t _reset); uint64_t getCaps() const; SwapChainGL* createSwapChain(void* _nwh, int32_t _width, int32_t _height); diff --git a/src/glcontext_wgl.cpp b/src/glcontext_wgl.cpp index d61ae47fc..4aadf5439 100644 --- a/src/glcontext_wgl.cpp +++ b/src/glcontext_wgl.cpp @@ -71,10 +71,10 @@ namespace bgfx { namespace gl HGLRC m_context; }; - static HGLRC createContext(HDC _hdc, const Resolution& _resolution) + static HGLRC createContext(HDC _hdc, const SwapChain& _swapChain) { - const bimg::ImageBlockInfo& colorBlockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_resolution.formatColor) ); - const bimg::ImageBlockInfo& depthStecilBlockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_resolution.formatDepthStencil) ); + const bimg::ImageBlockInfo& colorBlockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_swapChain.formatColor) ); + const bimg::ImageBlockInfo& depthStecilBlockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_swapChain.formatDepthStencil) ); PIXELFORMATDESCRIPTOR pfd; bx::memSet(&pfd, 0, sizeof(pfd) ); @@ -138,7 +138,7 @@ namespace bgfx { namespace gl ); } - void GlContext::create(const Resolution& _resolution) + void GlContext::create(const SwapChain& _swapChain, uint32_t _reset) { m_opengl32dll = bx::dlopen("opengl32.dll"); BGFX_FATAL(NULL != m_opengl32dll, Fatal::UnableToInitialize, "Failed to load opengl32.dll."); @@ -148,13 +148,15 @@ namespace bgfx { namespace gl // If g_platformHooks.nwh is NULL, the assumption is that GL context was created // by user (for example, using SDL, GLFW, etc.) - BX_WARN(NULL != g_platformData.nwh + BX_WARN(NULL != _swapChain.nwh || NULL != g_platformData.context - , "bgfx::setPlatform with valid window is not called. This might " + , "Init::swapChain has no valid window handle. This might " "be intentional when GL context is created by the user." ); - HWND nwh = (HWND)g_platformData.nwh; + m_nwh = _swapChain.nwh; + + HWND nwh = (HWND)m_nwh; m_ownsContext = NULL == g_platformData.context; @@ -244,7 +246,7 @@ namespace bgfx { namespace gl m_current = NULL; - m_swapInterval = !!(_resolution.reset & BGFX_RESET_VSYNC) ? 1 : 0; + m_swapInterval = !!(_reset & BGFX_RESET_VSYNC) ? 1 : 0; if (NULL != wglSwapIntervalEXT) { @@ -272,7 +274,7 @@ namespace bgfx { namespace gl HDC hdc = GetDC(hwnd); BGFX_FATAL(NULL != hdc, Fatal::UnableToInitialize, "GetDC failed!"); - HGLRC context = createContext(hdc, _resolution); + HGLRC context = createContext(hdc, _swapChain); wglGetExtensionsStringARB = wglGetProc("wglGetExtensionsStringARB"); wglChoosePixelFormatARB = wglGetProc("wglChoosePixelFormatARB"); @@ -289,8 +291,8 @@ namespace bgfx { namespace gl if (NULL != wglChoosePixelFormatARB && NULL != wglCreateContextAttribsARB) { - const bimg::ImageBlockInfo& colorBlockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_resolution.formatColor) ); - const bimg::ImageBlockInfo& depthStecilBlockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_resolution.formatDepthStencil) ); + const bimg::ImageBlockInfo& colorBlockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_swapChain.formatColor) ); + const bimg::ImageBlockInfo& depthStecilBlockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(_swapChain.formatDepthStencil) ); int32_t attrs[] = { @@ -376,14 +378,14 @@ namespace bgfx { namespace gl if (NULL == m_context) { - m_context = createContext(m_hdc, _resolution); + m_context = createContext(m_hdc, _swapChain); } int result = wglMakeCurrent(m_hdc, m_context); BGFX_FATAL(0 != result, Fatal::UnableToInitialize, "wglMakeCurrent failed!"); m_current = NULL; - m_swapInterval = !!(_resolution.reset & BGFX_RESET_VSYNC) ? 1 : 0; + m_swapInterval = !!(_reset & BGFX_RESET_VSYNC) ? 1 : 0; if (NULL != wglSwapIntervalEXT) { wglSwapIntervalEXT(m_swapInterval); @@ -410,7 +412,7 @@ namespace bgfx { namespace gl m_pixelFormat = 0; m_current = NULL; - ReleaseDC(NULL != m_dummyHwnd ? m_dummyHwnd : (HWND)g_platformData.nwh, m_hdc); + ReleaseDC(NULL != m_dummyHwnd ? m_dummyHwnd : (HWND)m_nwh, m_hdc); m_hdc = NULL; } @@ -424,9 +426,11 @@ namespace bgfx { namespace gl m_opengl32dll = NULL; } - void GlContext::resize(const Resolution& _resolution) + void GlContext::resize(const SwapChain& _swapChain, uint32_t _reset) { - const bool vsync = !!(_resolution.reset & BGFX_RESET_VSYNC); + BX_UNUSED(_swapChain); + + const bool vsync = !!(_reset & BGFX_RESET_VSYNC); m_swapInterval = vsync ? 1 : 0; if (NULL != wglSwapIntervalEXT) @@ -479,7 +483,7 @@ namespace bgfx { namespace gl if (NULL == _swapChain) { - if (NULL != g_platformData.nwh) + if (NULL != m_nwh) { SwapBuffers(m_hdc); } diff --git a/src/glcontext_wgl.h b/src/glcontext_wgl.h index e8c1cdff2..d94e5e9fc 100644 --- a/src/glcontext_wgl.h +++ b/src/glcontext_wgl.h @@ -73,6 +73,7 @@ typedef void (APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum z , m_pfd() , m_current(NULL) , m_opengl32dll(NULL) + , m_nwh(NULL) , m_context(NULL) , m_hdc(NULL) , m_dummyHwnd(NULL) @@ -83,9 +84,9 @@ typedef void (APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum z { } - void create(const Resolution& _resolution); + void create(const SwapChain& _swapChain, uint32_t _reset); void destroy(); - void resize(const Resolution& _resolution); + void resize(const SwapChain& _swapChain, uint32_t _reset); uint64_t getCaps() const; SwapChainGL* createSwapChain(void* _nwh, int32_t _width, int32_t _height); @@ -104,6 +105,7 @@ typedef void (APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum z PIXELFORMATDESCRIPTOR m_pfd; SwapChainGL* m_current; void* m_opengl32dll; + void* m_nwh; HGLRC m_context; HDC m_hdc; HWND m_dummyHwnd; diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 2b935adff..7c8fe4429 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -750,21 +750,20 @@ namespace bgfx { namespace d3d11 , m_agsDll(NULL) , m_ags(NULL) , m_featureLevel(D3D_FEATURE_LEVEL(0) ) - , m_swapChain(NULL) - , m_msaaRt(NULL) - , m_needPresent(false) , m_lost(false) , m_numWindows(0) , m_device(NULL) , m_deviceCtx(NULL) , m_annotation(NULL) , m_infoQueue(NULL) - , m_backBufferColor(NULL) - , m_backBufferDepthStencil(NULL) + , m_deviceInterfaceVersion(0) , m_currentColor(NULL) , m_currentDepthStencil(NULL) , m_captureTexture(NULL) , m_captureResolve(NULL) + , m_reset(BGFX_RESET_NONE) + , m_swapEffect(DXGI_SWAP_EFFECT_DISCARD) + , m_swapBufferCount(0) , m_maxAnisotropy(1) , m_depthClamp(false) , m_wireframe(false) @@ -806,7 +805,7 @@ namespace bgfx { namespace d3d11 m_fbh = BGFX_INVALID_HANDLE; bx::memSet(m_uniforms, 0, sizeof(m_uniforms) ); - bx::memSet(&m_resolution, 0, sizeof(m_resolution) ); + bx::memSet(&m_mainSwapChain, 0, sizeof(m_mainSwapChain) ); m_ags = NULL; m_agsDll = bx::dlopen( @@ -1091,9 +1090,8 @@ namespace bgfx { namespace d3d11 m_nvapi.shutdown(); } - m_msaaRt = NULL; + mainFrameBuffer().m_msaaRt = NULL; - if (NULL == g_platformData.backBuffer) { HRESULT hr = S_OK; @@ -1105,11 +1103,11 @@ namespace bgfx { namespace d3d11 #endif // BX_PLATFORM_LINUX || BX_PLATFORM_WINDOWS ; - m_swapBufferCount = bx::clamp(_init.resolution.numBackBuffers, 2, BGFX_CONFIG_MAX_BACK_BUFFERS); + m_swapBufferCount = bx::clamp(_init.swapChain.numBackBuffers, 2, BGFX_CONFIG_MAX_BACK_BUFFERS); bx::memSet(&m_scd, 0, sizeof(m_scd) ); - m_scd.width = _init.resolution.width; - m_scd.height = _init.resolution.height; + m_scd.width = _init.swapChain.width; + m_scd.height = _init.swapChain.height; /* * According to https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/converting-data-color-space , @@ -1121,37 +1119,37 @@ namespace bgfx { namespace d3d11 * is incompatible with the flip presentation model, which is desirable for various reasons including * player embedding. */ - m_scd.format = s_textureFormat[_init.resolution.formatColor].m_fmt; + m_scd.format = s_textureFormat[_init.swapChain.formatColor].m_fmt; updateMsaa(m_scd.format); - m_scd.sampleDesc = s_msaa[(_init.resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; + m_scd.sampleDesc = s_msaa[(_init.swapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT]; m_scd.bufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; m_scd.bufferCount = m_swapBufferCount; - m_scd.scaling = 0 == g_platformData.ndt + m_scd.scaling = 0 == _init.swapChain.ndt ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH ; m_scd.swapEffect = m_swapEffect; - m_scd.alphaMode = (_init.resolution.reset & BGFX_RESET_TRANSPARENT_BACKBUFFER) + m_scd.alphaMode = (_init.swapChain.flags & BGFX_SWAP_CHAIN_TRANSPARENT_BACKBUFFER) ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE ; m_scd.flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; - m_scd.maxFrameLatency = bx::min(_init.resolution.maxFrameLatency, BGFX_CONFIG_MAX_FRAME_LATENCY); + m_scd.maxFrameLatency = bx::min(_init.swapChain.maxFrameLatency, BGFX_CONFIG_MAX_FRAME_LATENCY); m_scd.waitable = false; - m_scd.nwh = g_platformData.nwh; - m_scd.ndt = g_platformData.ndt; + m_scd.nwh = _init.swapChain.nwh; + m_scd.ndt = _init.swapChain.ndt; m_scd.windowed = true; if (NULL != m_scd.nwh) { hr = m_dxgi.createSwapChain(m_device , m_scd - , &m_swapChain + , &mainFrameBuffer().m_swapChain ); if (FAILED(hr) ) @@ -1171,7 +1169,7 @@ namespace bgfx { namespace d3d11 m_scd.swapEffect = m_swapEffect; hr = m_dxgi.createSwapChain(m_device , m_scd - , &m_swapChain + , &mainFrameBuffer().m_swapChain ); if (FAILED(hr) ) @@ -1181,39 +1179,19 @@ namespace bgfx { namespace d3d11 } } - m_resolution = _init.resolution; - m_resolution.reset = _init.resolution.reset & (~BGFX_RESET_INTERNAL_FORCE); + m_mainSwapChain = _init.swapChain; + m_reset = _init.reset & (~BGFX_RESET_INTERNAL_FORCE); - m_textVideoMem.resize(false, _init.resolution.width, _init.resolution.height); + m_textVideoMem.resize(false, _init.swapChain.width, _init.swapChain.height); m_textVideoMem.clear(); - if (1 < m_scd.sampleDesc.Count) - { - D3D11_TEXTURE2D_DESC desc; - desc.Width = m_scd.width; - desc.Height = m_scd.height; - desc.MipLevels = 1; - desc.ArraySize = 1; - /* - * According to https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/converting-data-color-space , - * ONLY the backbuffer from swapchain can be created without *_SRGB format, custom backbuffer should be created the same - * format as well as render target view. - */ - desc.Format = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) - ? s_textureFormat[m_resolution.formatColor].m_fmtSrgb - : s_textureFormat[m_resolution.formatColor].m_fmt - ; - desc.SampleDesc = m_scd.sampleDesc; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_RENDER_TARGET; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - DX_CHECK(m_device->CreateTexture2D(&desc, NULL, &m_msaaRt) ); - } + mainFrameBuffer().m_desc = m_mainSwapChain; + mainFrameBuffer().m_nwh = m_scd.nwh; + mainFrameBuffer().m_num = 1; } #if BX_PLATFORM_WINDOWS - DX_CHECK(m_dxgi.m_factory->MakeWindowAssociation( (HWND)g_platformData.nwh, 0 + DX_CHECK(m_dxgi.m_factory->MakeWindowAssociation( (HWND)_init.swapChain.nwh, 0 | DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER ) ); @@ -1225,16 +1203,6 @@ namespace bgfx { namespace d3d11 goto error; } } - else - { - bx::memSet(&m_scd, 0, sizeof(m_scd) ); - m_scd.sampleDesc.Count = 1; - m_scd.sampleDesc.Quality = 0; - m_scd.width = _init.resolution.width; - m_scd.height = _init.resolution.height; - m_backBufferColor = (ID3D11RenderTargetView*)g_platformData.backBuffer; - m_backBufferDepthStencil = (ID3D11DepthStencilView*)g_platformData.backBufferDS; - } } m_numWindows = 1; @@ -1750,11 +1718,11 @@ namespace bgfx { namespace d3d11 case ErrorState::LoadedDXGI: DX_RELEASE(m_annotation, 1); DX_RELEASE_W(m_infoQueue, 0); - DX_RELEASE(m_msaaRt, 0); + DX_RELEASE(mainFrameBuffer().m_msaaRt, 0); m_dxgi.removeSwapChain(m_scd); - DX_RELEASE(m_swapChain, 0); + DX_RELEASE(mainFrameBuffer().m_swapChain, 0); DX_RELEASE(m_deviceCtx, 0); DX_RELEASE(m_device, 0); @@ -1851,11 +1819,11 @@ namespace bgfx { namespace d3d11 DX_RELEASE(m_annotation, 1); dumpInfoQueue(); DX_RELEASE_W(m_infoQueue, 0); - DX_RELEASE(m_msaaRt, 0); + DX_RELEASE(mainFrameBuffer().m_msaaRt, 0); m_dxgi.removeSwapChain(m_scd); - DX_RELEASE(m_swapChain, 0); + DX_RELEASE(mainFrameBuffer().m_swapChain, 0); DX_RELEASE(m_deviceCtx, 0); DX_RELEASE(m_device, 0); @@ -2097,14 +2065,6 @@ namespace bgfx { namespace d3d11 release(mem); } - void overrideInternal(TextureHandle _handle, uintptr_t _ptr, uint16_t _layerIndex) override - { - // Resource ref. counts might be messed up outside of bgfx. - // Disabling ref. count check once texture is overridden. - setGraphicsDebuggerPresent(true); - m_textures[_handle.idx].overrideInternal(_ptr, _layerIndex); - } - uintptr_t getInternal(TextureHandle _handle) override { // Resource ref. counts might be messed up outside of bgfx. @@ -2123,13 +2083,13 @@ namespace bgfx { namespace d3d11 m_frameBuffers[_handle.idx].create(_num, _attachment); } - void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) override + void createFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override { for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) { FrameBufferHandle handle = m_windows[ii]; if (isValid(handle) - && m_frameBuffers[handle.idx].m_nwh == _nwh) + && m_frameBuffers[handle.idx].m_nwh == _desc.nwh) { destroyFrameBuffer(handle); } @@ -2137,7 +2097,12 @@ namespace bgfx { namespace d3d11 uint16_t denseIdx = m_numWindows++; m_windows[denseIdx] = _handle; - m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _format, _depthFormat); + m_frameBuffers[_handle.idx].create(denseIdx, _desc); + } + + void resizeFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override + { + m_frameBuffers[_handle.idx].update(_desc); } void destroyFrameBuffer(FrameBufferHandle _handle) override @@ -2187,10 +2152,8 @@ namespace bgfx { namespace d3d11 void requestScreenShot(FrameBufferHandle _handle, const char* _filePath) override { - IDXGISwapChain* swapChain = isValid(_handle) - ? m_frameBuffers[_handle.idx].m_swapChain - : m_swapChain - ; + FrameBufferD3D11& frameBuffer = getFrameBuffer(_handle); + IDXGISwapChain* swapChain = frameBuffer.m_swapChain; if (NULL == swapChain) { @@ -2201,6 +2164,17 @@ namespace bgfx { namespace d3d11 ID3D11Texture2D* backBuffer; DX_CHECK(swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) ); + if (NULL != frameBuffer.m_msaaRt) + { + m_deviceCtx->ResolveSubresource( + backBuffer + , 0 + , frameBuffer.m_msaaRt + , 0 + , frameBuffer.getSwapChainDesc().format + ); + } + D3D11_TEXTURE2D_DESC backBufferDesc; backBuffer->GetDesc(&backBufferDesc); @@ -2350,14 +2324,15 @@ namespace bgfx { namespace d3d11 void submit(Frame* _render, const ClearQuad& _clearQuad, const MipGen& _mipGen, TextVideoMemBlitter& _textVideoMemBlitter) override; - void dbgTextRenderBegin(TextVideoMemBlitter& _blitter) override + void dbgTextRenderBegin(TextVideoMemBlitter& _blitter, FrameBufferHandle _handle) override { ID3D11DeviceContext* deviceCtx = m_deviceCtx; - const uint32_t width = m_scd.width; - const uint32_t height = m_scd.height; + const FrameBufferD3D11& frameBuffer = getFrameBuffer(_handle); + const uint32_t width = frameBuffer.m_width; + const uint32_t height = frameBuffer.m_height; - setFrameBuffer(BGFX_INVALID_HANDLE, false, false); + setFrameBuffer(_handle, false, false); D3D11_VIEWPORT vp; vp.TopLeftX = 0; @@ -2427,24 +2402,12 @@ namespace bgfx { namespace d3d11 void preReset() { - m_needPresent = false; - if (m_timerQuerySupport) { m_gpuTimer.preReset(); } m_occlusionQuery.preReset(); - if (NULL == g_platformData.backBufferDS) - { - DX_RELEASE(m_backBufferDepthStencil, 0); - } - - if (NULL != m_swapChain) - { - DX_RELEASE(m_backBufferColor, 0); - } - for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) { m_frameBuffers[ii].preReset(); @@ -2457,34 +2420,6 @@ namespace bgfx { namespace d3d11 void postReset() { - if (NULL != m_swapChain) - { - ID3D11Texture2D* backBufferColor = NULL; - if (NULL == m_msaaRt) - { - DX_CHECK(m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBufferColor) ); - } - - D3D11_RENDER_TARGET_VIEW_DESC desc; - desc.ViewDimension = (m_resolution.reset & BGFX_RESET_MSAA_MASK) - ? D3D11_RTV_DIMENSION_TEXTURE2DMS - : D3D11_RTV_DIMENSION_TEXTURE2D - ; - desc.Texture2D.MipSlice = 0; - - /* go find the srgb version of this format to make a render target view - * with the srgb version. this is OK because of this: - * https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/converting-data-color-space - */ - desc.Format = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) - ? s_textureFormat[m_resolution.formatColor].m_fmtSrgb - : s_textureFormat[m_resolution.formatColor].m_fmt - ; - - DX_CHECK(m_device->CreateRenderTargetView(NULL == m_msaaRt ? backBufferColor : m_msaaRt, &desc, &m_backBufferColor) ); - DX_RELEASE(backBufferColor, 0); - } - if (m_timerQuerySupport) { m_gpuTimer.postReset(); @@ -2492,36 +2427,19 @@ namespace bgfx { namespace d3d11 m_occlusionQuery.postReset(); - if (bimg::isDepth(bimg::TextureFormat::Enum(m_resolution.formatDepthStencil) ) ) - { - D3D11_TEXTURE2D_DESC dsd; - dsd.Width = bx::max(m_scd.width, 1); - dsd.Height = bx::max(m_scd.height, 1); - dsd.MipLevels = 1; - dsd.ArraySize = 1; - dsd.Format = s_textureFormat[m_resolution.formatDepthStencil].m_fmtDsv; - dsd.SampleDesc = m_scd.sampleDesc; - dsd.Usage = D3D11_USAGE_DEFAULT; - dsd.BindFlags = D3D11_BIND_DEPTH_STENCIL; - dsd.CPUAccessFlags = 0; - dsd.MiscFlags = 0; - - ID3D11Texture2D* depthStencil; - DX_CHECK(m_device->CreateTexture2D(&dsd, NULL, &depthStencil) ); - DX_CHECK(m_device->CreateDepthStencilView(depthStencil, NULL, &m_backBufferDepthStencil) ); - DX_RELEASE(depthStencil, 0); - } - - m_deviceCtx->OMSetRenderTargets(1, &m_backBufferColor, m_backBufferDepthStencil); - - m_currentColor = m_backBufferColor; - m_currentDepthStencil = m_backBufferDepthStencil; + mainFrameBuffer().m_desc = m_mainSwapChain; for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) { m_frameBuffers[ii].postReset(); } + FrameBufferD3D11& mainFb = mainFrameBuffer(); + m_deviceCtx->OMSetRenderTargets(1, &mainFb.m_rtv[0], mainFb.m_dsv); + + m_currentColor = mainFb.m_rtv[0]; + m_currentDepthStencil = mainFb.m_dsv; + capturePostReset(); } @@ -2557,7 +2475,7 @@ namespace bgfx { namespace d3d11 HRESULT hr = S_OK; uint32_t syncInterval = BX_ENABLED(!BX_PLATFORM_WINDOWS) ? 1 // sync interval of 0 is not supported on WinRT - : !!(m_resolution.reset & BGFX_RESET_VSYNC) + : !!(m_reset & BGFX_RESET_VSYNC) ; uint32_t presentFlags = 0; @@ -2574,12 +2492,12 @@ namespace bgfx { namespace d3d11 if (SUCCEEDED(hr) ) { - if (NULL != m_swapChain - && m_needPresent) - { - hr = m_swapChain->Present(syncInterval, presentFlags); + FrameBufferD3D11& mainFb = mainFrameBuffer(); - m_needPresent = false; + if (mainFb.isSwapChain() + && mainFb.m_needPresent) + { + hr = mainFb.present(syncInterval, presentFlags); } else { @@ -2639,21 +2557,21 @@ namespace bgfx { namespace d3d11 #if BX_PLATFORM_WINRT // SwapChainPanels can be dynamically updated if (m_scd.ndt == reinterpret_cast(2) - && (m_scd.nwh != g_platformData.nwh || m_scd.ndt != g_platformData.ndt) ) + && (m_scd.nwh != m_mainSwapChain.nwh || m_scd.ndt != m_mainSwapChain.ndt) ) { // Remove swap chain from SwapChainPanel (nwh) if applicable m_dxgi.removeSwapChain(m_scd); // Update nwh after removing swap chain - m_scd.nwh = g_platformData.nwh; - m_scd.ndt = g_platformData.ndt; + m_scd.nwh = m_mainSwapChain.nwh; + m_scd.ndt = m_mainSwapChain.ndt; } #endif } - bool updateResolution(const Resolution& _resolution) + bool updateResolution(const SwapChain& _swapChain, uint32_t _reset) { - const bool suspended = !!( _resolution.reset & BGFX_RESET_SUSPEND); - const bool wasSuspended = !!(m_resolution.reset & BGFX_RESET_SUSPEND); + const bool suspended = !!( _reset & BGFX_RESET_SUSPEND); + const bool wasSuspended = !!(m_reset & BGFX_RESET_SUSPEND); if (suspended && wasSuspended) { return true; @@ -2664,17 +2582,17 @@ namespace bgfx { namespace d3d11 m_deviceCtx->ClearState(); m_dxgi.trim(); suspend(m_device); - m_resolution.reset |= BGFX_RESET_SUSPEND; + m_reset |= BGFX_RESET_SUSPEND; return true; } else if (wasSuspended) { resume(m_device); - m_resolution.reset &= ~BGFX_RESET_SUSPEND; + m_reset &= ~BGFX_RESET_SUSPEND; } uint32_t maxAnisotropy = 1; - if (!!(_resolution.reset & BGFX_RESET_MAXANISOTROPY) ) + if (!!(_reset & BGFX_RESET_MAXANISOTROPY) ) { maxAnisotropy = (m_featureLevel == D3D_FEATURE_LEVEL_9_1) ? D3D_FL9_1_DEFAULT_MAX_ANISOTROPY @@ -2689,7 +2607,7 @@ namespace bgfx { namespace d3d11 } bool depthClamp = true - && !!(_resolution.reset & BGFX_RESET_DEPTH_CLAMP) + && !!(_reset & BGFX_RESET_DEPTH_CLAMP) && m_featureLevel > D3D_FEATURE_LEVEL_9_3 // disabling depth clamp is only supported on 10_0+ ; @@ -2699,10 +2617,10 @@ namespace bgfx { namespace d3d11 m_rasterizerStateCache.invalidate(); } - if (_resolution.reset & BGFX_RESET_VSYNC) - m_resolution.reset |= BGFX_RESET_VSYNC; + if (_reset & BGFX_RESET_VSYNC) + m_reset |= BGFX_RESET_VSYNC; else - m_resolution.reset &= ~BGFX_RESET_VSYNC; + m_reset &= ~BGFX_RESET_VSYNC; const uint32_t maskFlags = ~(0 | BGFX_RESET_MAXANISOTROPY @@ -2711,85 +2629,60 @@ namespace bgfx { namespace d3d11 | BGFX_RESET_VSYNC ); - if (m_resolution.width != _resolution.width - || m_resolution.height != _resolution.height - || m_resolution.formatColor != _resolution.formatColor - || m_resolution.formatDepthStencil != _resolution.formatDepthStencil - || (m_resolution.reset&maskFlags) != (_resolution.reset&maskFlags) + if (m_mainSwapChain.width != _swapChain.width + || m_mainSwapChain.height != _swapChain.height + || m_mainSwapChain.formatColor != _swapChain.formatColor + || m_mainSwapChain.formatDepthStencil != _swapChain.formatDepthStencil + || m_mainSwapChain.nwh != _swapChain.nwh + || m_mainSwapChain.ndt != _swapChain.ndt + || (m_reset&maskFlags) != (_reset&maskFlags) ) { - uint32_t flags = _resolution.reset & (~BGFX_RESET_INTERNAL_FORCE); + uint32_t flags = _reset & (~BGFX_RESET_INTERNAL_FORCE); bool resize = true && !BX_ENABLED(BX_PLATFORM_XBOXONE) - && (m_resolution.reset&BGFX_RESET_MSAA_MASK) == (flags&BGFX_RESET_MSAA_MASK) + && (m_mainSwapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK) == (_swapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK) ; - m_resolution = _resolution; - m_resolution.reset = flags; + m_mainSwapChain = _swapChain; + m_reset = flags; - m_textVideoMem.resize(false, _resolution.width, _resolution.height); + m_textVideoMem.resize(false, _swapChain.width, _swapChain.height); m_textVideoMem.clear(); - m_scd.width = _resolution.width; - m_scd.height = _resolution.height; + m_scd.width = _swapChain.width; + m_scd.height = _swapChain.height; // see comment in init() about why we don't worry about BGFX_RESET_SRGB_BACKBUFFER here - m_scd.format = s_textureFormat[_resolution.formatColor].m_fmt; + m_scd.format = s_textureFormat[_swapChain.formatColor].m_fmt; preReset(); m_deviceCtx->Flush(); m_deviceCtx->ClearState(); - if (NULL == m_swapChain) + if (mainFrameBuffer().isSwapChain() ) { - // Updated backbuffer if it changed in PlatformData. - m_backBufferColor = (ID3D11RenderTargetView*)g_platformData.backBuffer; - m_backBufferDepthStencil = (ID3D11DepthStencilView*)g_platformData.backBufferDS; - } - else - { - DX_RELEASE(m_msaaRt, 0); - if (resize) { m_deviceCtx->OMSetRenderTargets(1, s_zero.m_rtv, NULL); - DX_CHECK(m_dxgi.resizeBuffers(m_swapChain, m_scd) ); + DX_CHECK(m_dxgi.resizeBuffers(mainFrameBuffer().m_swapChain, m_scd) ); } else { updateMsaa(m_scd.format); - m_scd.sampleDesc = s_msaa[(m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; + m_scd.sampleDesc = s_msaa[(m_mainSwapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT]; m_dxgi.removeSwapChain(m_scd); - DX_RELEASE(m_swapChain, 0); + DX_RELEASE(mainFrameBuffer().m_swapChain, 0); HRESULT hr = m_dxgi.createSwapChain(m_device , m_scd - , &m_swapChain + , &mainFrameBuffer().m_swapChain ); BGFX_FATAL(SUCCEEDED(hr), bgfx::Fatal::UnableToInitialize, "Failed to create swap chain."); } - - if (1 < m_scd.sampleDesc.Count) - { - D3D11_TEXTURE2D_DESC desc; - desc.Width = m_scd.width; - desc.Height = m_scd.height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) - ? s_textureFormat[m_resolution.formatColor].m_fmtSrgb - : s_textureFormat[m_resolution.formatColor].m_fmt - ; - desc.SampleDesc = m_scd.sampleDesc; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_RENDER_TARGET; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - DX_CHECK(m_device->CreateTexture2D(&desc, NULL, &m_msaaRt) ); - } } postReset(); @@ -2857,14 +2750,31 @@ namespace bgfx { namespace d3d11 } } + FrameBufferD3D11& getFrameBuffer(FrameBufferHandle _fbh) + { + return m_frameBuffers[isValid(_fbh) ? _fbh.idx : kMainFrameBufferIdx]; + } + + const FrameBufferD3D11& getFrameBuffer(FrameBufferHandle _fbh) const + { + return m_frameBuffers[isValid(_fbh) ? _fbh.idx : kMainFrameBufferIdx]; + } + + FrameBufferD3D11& mainFrameBuffer() + { + return m_frameBuffers[kMainFrameBufferIdx]; + } + void setFrameBuffer(FrameBufferHandle _fbh, bool _msaa = true, bool _needPresent = true) { resolveFrameBuffer(_fbh); if (!isValid(_fbh) ) { - m_currentColor = m_backBufferColor; - m_currentDepthStencil = m_backBufferDepthStencil; + FrameBufferD3D11& frameBuffer = getFrameBuffer(_fbh); + + m_currentColor = frameBuffer.m_rtv[0]; + m_currentDepthStencil = frameBuffer.m_dsv; m_deviceCtx->OMSetRenderTargetsAndUnorderedAccessViews( 1 @@ -2875,7 +2785,7 @@ namespace bgfx { namespace d3d11 , NULL , NULL ); - m_needPresent |= _needPresent; + frameBuffer.m_needPresent |= _needPresent; } else { @@ -3608,10 +3518,10 @@ namespace bgfx { namespace d3d11 void capturePostReset() { - if (m_resolution.reset&BGFX_RESET_CAPTURE) + if (m_reset&BGFX_RESET_CAPTURE) { ID3D11Texture2D* backBuffer; - DX_CHECK(m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) ); + DX_CHECK(mainFrameBuffer().m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) ); D3D11_TEXTURE2D_DESC backBufferDesc; backBuffer->GetDesc(&backBufferDesc); @@ -3657,7 +3567,7 @@ namespace bgfx { namespace d3d11 if (NULL != m_captureTexture) { ID3D11Texture2D* backBuffer; - DX_CHECK(m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) ); + DX_CHECK(mainFrameBuffer().m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) ); if (NULL == m_captureResolve) { @@ -3942,10 +3852,6 @@ namespace bgfx { namespace d3d11 D3D_FEATURE_LEVEL m_featureLevel; - Dxgi::SwapChainI* m_swapChain; - ID3D11Texture2D* m_msaaRt; - - bool m_needPresent; bool m_lost; uint16_t m_numWindows; FrameBufferHandle m_windows[BGFX_CONFIG_MAX_FRAME_BUFFERS]; @@ -3960,17 +3866,16 @@ namespace bgfx { namespace d3d11 uint32_t m_deviceInterfaceVersion; - ID3D11RenderTargetView* m_backBufferColor; - ID3D11DepthStencilView* m_backBufferDepthStencil; ID3D11RenderTargetView* m_currentColor; ID3D11DepthStencilView* m_currentDepthStencil; ID3D11Texture2D* m_captureTexture; ID3D11Texture2D* m_captureResolve; - Resolution m_resolution; + SwapChain m_mainSwapChain; + uint32_t m_reset; - SwapChainDesc m_scd; + DxgiSwapChainDesc m_scd; DXGI_SWAP_EFFECT m_swapEffect; uint32_t m_swapBufferCount; uint32_t m_maxAnisotropy; @@ -3983,8 +3888,7 @@ namespace bgfx { namespace d3d11 ProgramD3D11 m_program[BGFX_CONFIG_MAX_PROGRAMS]; TextureD3D11 m_textures[BGFX_CONFIG_MAX_TEXTURES]; VertexLayout m_vertexLayouts[BGFX_CONFIG_MAX_VERTEX_LAYOUTS]; - FrameBufferD3D11 m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS]; - void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS]; + FrameBufferD3D11 m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS+1]; void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS]; Matrix4 m_predefinedUniforms[PredefinedUniform::Count]; UniformRegistry m_uniformReg; @@ -5278,44 +5182,6 @@ namespace bgfx { namespace d3d11 } } - void TextureD3D11::overrideInternal(uintptr_t _ptr, uint16_t _layerIndex) - { - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc{}; - - const bool readable = NULL != m_srv; - - if (readable) - { - m_srv->GetDesc(&srvDesc); - } - - switch (srvDesc.ViewDimension) - { - case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: - srvDesc.Texture2DArray.FirstArraySlice = _layerIndex; - srvDesc.Texture2DArray.ArraySize = 1; - break; - - case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: - srvDesc.Texture2DMSArray.FirstArraySlice = _layerIndex; - srvDesc.Texture2DMSArray.ArraySize = 1; - break; - - default: - break; - } - - destroy(); - - m_flags |= BGFX_SAMPLER_INTERNAL_SHARED; - m_ptr = (ID3D11Resource*)_ptr; - - if (readable) - { - s_renderD3D11->m_device->CreateShaderResourceView(m_ptr, &srvDesc, &m_srv); - } - } - void TextureD3D11::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) { if (0 != (m_flags & BGFX_TEXTURE_INTERNAL_VIDEO_DECODE_DST) ) @@ -5624,70 +5490,194 @@ namespace bgfx { namespace d3d11 postReset(); } - void FrameBufferD3D11::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) + void FrameBufferD3D11::create(uint16_t _denseIdx, const SwapChain& _desc) { - SwapChainDesc scd; - bx::memCopy(&scd, &s_renderD3D11->m_scd, sizeof(SwapChainDesc) ); - scd.format = TextureFormat::Count == _format ? scd.format : s_textureFormat[_format].m_fmt; - scd.width = _width; - scd.height = _height; - scd.nwh = _nwh; - scd.ndt = NULL; - scd.sampleDesc = s_msaa[0]; + m_desc = _desc; + m_nwh = _desc.nwh; + m_denseIdx = _denseIdx; + m_num = 1; - ID3D11Device* device = s_renderD3D11->m_device; + const DxgiSwapChainDesc scd = getSwapChainDesc(); - HRESULT hr = s_renderD3D11->m_dxgi.createSwapChain(device + HRESULT hr = s_renderD3D11->m_dxgi.createSwapChain(s_renderD3D11->m_device , scd , &m_swapChain ); BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain."); + if (FAILED(hr) ) + { + m_swapChain = NULL; + m_num = 0; + return; + } + #if BX_PLATFORM_WINDOWS DX_CHECK(s_renderD3D11->m_dxgi.m_factory->MakeWindowAssociation( - (HWND)_nwh + (HWND)_desc.nwh , 0 | DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER ) ); #endif // BX_PLATFORM_WINDOWS - ID3D11Resource* ptr; - DX_CHECK(m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&ptr) ); - DX_CHECK(device->CreateRenderTargetView(ptr, NULL, &m_rtv[0]) ); - DX_RELEASE(ptr, 0); + createSwapChainViews(); + } - DXGI_FORMAT fmtDsv = bimg::isDepth(bimg::TextureFormat::Enum(_depthFormat) ) - ? s_textureFormat[_depthFormat].m_fmtDsv - : DXGI_FORMAT_D24_UNORM_S8_UINT + void FrameBufferD3D11::update(const SwapChain& _desc) + { + if (!isSwapChain() ) + { + create(m_denseIdx, _desc); + return; + } + + m_desc = _desc; + m_nwh = _desc.nwh; + + const DxgiSwapChainDesc scd = getSwapChainDesc(); + + s_renderD3D11->m_deviceCtx->OMSetRenderTargets(0, NULL, NULL); + destroySwapChainViews(); + + DX_CHECK(s_renderD3D11->m_dxgi.resizeBuffers(m_swapChain, scd) ); + + createSwapChainViews(); + } + + DxgiSwapChainDesc FrameBufferD3D11::getSwapChainDesc() const + { + DxgiSwapChainDesc scd; + bx::memCopy(&scd, &s_renderD3D11->m_scd, sizeof(DxgiSwapChainDesc) ); + scd.format = s_textureFormat[m_desc.formatColor].m_fmt; + scd.width = m_desc.width; + scd.height = m_desc.height; + scd.nwh = m_desc.nwh; + scd.ndt = m_desc.ndt; + scd.sampleDesc = s_msaa[(m_desc.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT]; + + return scd; + } + + void FrameBufferD3D11::createSwapChainViews() + { + ID3D11Device* device = s_renderD3D11->m_device; + + const DxgiSwapChainDesc scd = getSwapChainDesc(); + + if (1 < scd.sampleDesc.Count + && NULL == m_msaaRt) + { + D3D11_TEXTURE2D_DESC desc; + desc.Width = scd.width; + desc.Height = scd.height; + desc.MipLevels = 1; + desc.ArraySize = 1; + + // https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/converting-data-color-space + desc.Format = (m_desc.flags & BGFX_SWAP_CHAIN_SRGB_BACKBUFFER) + ? s_textureFormat[m_desc.formatColor].m_fmtSrgb + : s_textureFormat[m_desc.formatColor].m_fmt + ; + desc.SampleDesc = scd.sampleDesc; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + DX_CHECK(device->CreateTexture2D(&desc, NULL, &m_msaaRt) ); + } + + ID3D11Texture2D* backBufferColor = NULL; + if (NULL == m_msaaRt) + { + DX_CHECK(m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBufferColor) ); + } + + D3D11_RENDER_TARGET_VIEW_DESC rtvd; + rtvd.ViewDimension = (m_desc.flags & BGFX_SWAP_CHAIN_MSAA_MASK) + ? D3D11_RTV_DIMENSION_TEXTURE2DMS + : D3D11_RTV_DIMENSION_TEXTURE2D ; - D3D11_TEXTURE2D_DESC dsd; - dsd.Width = scd.width; - dsd.Height = scd.height; - dsd.MipLevels = 1; - dsd.ArraySize = 1; - dsd.Format = fmtDsv; - dsd.SampleDesc = scd.sampleDesc; - dsd.Usage = D3D11_USAGE_DEFAULT; - dsd.BindFlags = D3D11_BIND_DEPTH_STENCIL; - dsd.CPUAccessFlags = 0; - dsd.MiscFlags = 0; + rtvd.Texture2D.MipSlice = 0; - ID3D11Texture2D* depthStencil; - DX_CHECK(device->CreateTexture2D(&dsd, NULL, &depthStencil) ); - DX_CHECK(device->CreateDepthStencilView(depthStencil, NULL, &m_dsv) ); - DX_RELEASE(depthStencil, 0); + /* go find the srgb version of this format to make a render target view + * with the srgb version. this is OK because of this: + * https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/converting-data-color-space + */ + rtvd.Format = (m_desc.flags & BGFX_SWAP_CHAIN_SRGB_BACKBUFFER) + ? s_textureFormat[m_desc.formatColor].m_fmtSrgb + : s_textureFormat[m_desc.formatColor].m_fmt + ; - m_nwh = _nwh; - m_denseIdx = _denseIdx; - m_num = 1; + DX_CHECK(device->CreateRenderTargetView( + NULL == m_msaaRt ? backBufferColor : m_msaaRt + , &rtvd + , &m_rtv[0] + ) ); + DX_RELEASE(backBufferColor, 0); + + if (isValid(m_desc.depth) ) + { + const TextureD3D11& texture = s_renderD3D11->m_textures[m_desc.depth.idx]; + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvd; + dsvd.Format = s_textureFormat[texture.m_textureFormat].m_fmtDsv; + dsvd.ViewDimension = 1 < scd.sampleDesc.Count + ? D3D11_DSV_DIMENSION_TEXTURE2DMS + : D3D11_DSV_DIMENSION_TEXTURE2D + ; + dsvd.Flags = 0; + dsvd.Texture2D.MipSlice = 0; + + DX_CHECK(device->CreateDepthStencilView( + NULL == texture.m_rt ? texture.m_ptr : texture.m_rt + , &dsvd + , &m_dsv + ) ); + } + else if (bimg::isDepth(bimg::TextureFormat::Enum(m_desc.formatDepthStencil) ) ) + { + D3D11_TEXTURE2D_DESC dsd; + dsd.Width = bx::max(scd.width, 1); + dsd.Height = bx::max(scd.height, 1); + dsd.MipLevels = 1; + dsd.ArraySize = 1; + dsd.Format = s_textureFormat[m_desc.formatDepthStencil].m_fmtDsv; + dsd.SampleDesc = scd.sampleDesc; + dsd.Usage = D3D11_USAGE_DEFAULT; + dsd.BindFlags = D3D11_BIND_DEPTH_STENCIL; + dsd.CPUAccessFlags = 0; + dsd.MiscFlags = 0; + + ID3D11Texture2D* depthStencil; + DX_CHECK(device->CreateTexture2D(&dsd, NULL, &depthStencil) ); + DX_CHECK(device->CreateDepthStencilView(depthStencil, NULL, &m_dsv) ); + DX_RELEASE(depthStencil, 0); + } + + m_width = scd.width; + m_height = scd.height; + } + + void FrameBufferD3D11::destroySwapChainViews() + { + DX_RELEASE(m_srv[0], 0); + DX_RELEASE(m_rtv[0], 0); + DX_RELEASE(m_dsv, 0); + DX_RELEASE(m_msaaRt, 0); } uint16_t FrameBufferD3D11::destroy() { - preReset(true); - - DX_RELEASE(m_swapChain, 0); + if (isSwapChain() ) + { + destroySwapChainViews(); + DX_RELEASE(m_swapChain, 0); + } + else + { + preReset(true); + } m_num = 0; m_nwh = NULL; @@ -5702,6 +5692,15 @@ namespace bgfx { namespace d3d11 void FrameBufferD3D11::preReset(bool _force) { + if (isSwapChain() ) + { + destroySwapChainViews(); + + m_needPresent = false; + + return; + } + if (0 < m_numTh || _force) { @@ -5717,6 +5716,13 @@ namespace bgfx { namespace d3d11 void FrameBufferD3D11::postReset() { + if (isSwapChain() ) + { + createSwapChainViews(); + + return; + } + m_width = 0; m_height = 0; m_needsQuadClear = false; @@ -5990,22 +5996,37 @@ namespace bgfx { namespace d3d11 void FrameBufferD3D11::set() { s_renderD3D11->m_deviceCtx->OMSetRenderTargets(m_num, m_rtv, m_dsv); - m_needPresent = UINT16_MAX != m_denseIdx; + m_needPresent = isSwapChain(); s_renderD3D11->m_currentColor = m_rtv[0]; s_renderD3D11->m_currentDepthStencil = m_dsv; } HRESULT FrameBufferD3D11::present(uint32_t _syncInterval, uint32_t _flags) { - if (m_needPresent) + if (!m_needPresent) { - HRESULT hr = m_swapChain->Present(_syncInterval, _flags); - hr = !isLost(hr) ? S_OK : hr; - m_needPresent = false; - return hr; + return S_OK; } - return S_OK; + if (NULL != m_msaaRt) + { + ID3D11Texture2D* backBufferColor; + DX_CHECK(m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBufferColor) ); + s_renderD3D11->m_deviceCtx->ResolveSubresource( + backBufferColor + , 0 + , m_msaaRt + , 0 + , getSwapChainDesc().format + ); + DX_RELEASE(backBufferColor, 0); + } + + HRESULT hr = m_swapChain->Present(_syncInterval, _flags); + hr = !isLost(hr) ? S_OK : hr; + m_needPresent = false; + + return hr; } void TimerQueryD3D11::postReset() @@ -6545,7 +6566,7 @@ namespace bgfx { namespace d3d11 updateNativeWindow(); - if (updateResolution(_render->m_resolution) ) + if (updateResolution(_render->m_mainSwapChain, _render->m_reset) ) { return; } @@ -7480,7 +7501,7 @@ namespace bgfx { namespace d3d11 if (0 < _render->m_numRenderItems) { - if (0 != (m_resolution.reset & BGFX_RESET_FLUSH_AFTER_RENDER) ) + if (0 != (m_reset & BGFX_RESET_FLUSH_AFTER_RENDER) ) { deviceCtx->Flush(); } @@ -7542,7 +7563,7 @@ namespace bgfx { namespace d3d11 { BGFX_D3D11_PROFILER_BEGIN_LITERAL("debugstats", kColorFrame); - m_needPresent = true; + getFrameBuffer(_render->m_debugFrameBuffer).m_needPresent = true; TextVideoMem& tvm = m_textVideoMem; static int64_t next = timeEnd; @@ -7602,12 +7623,12 @@ namespace bgfx { namespace d3d11 , freq/frameTime ); - const uint32_t msaa = (m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + const uint32_t msaa = (m_mainSwapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT; tvm.printf(10, pos++, 0x8b, " Reset flags: [%c] vsync, [%c] MSAAx%d, [%c] MaxAnisotropy " - , !!(m_resolution.reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' + , !!(m_reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' , 0 != msaa ? '\xfe' : ' ' , 1<m_debugFrameBuffer, _render->m_debugTextScale); BGFX_D3D11_PROFILER_END(); } @@ -7680,21 +7701,13 @@ namespace bgfx { namespace d3d11 { BGFX_D3D11_PROFILER_BEGIN_LITERAL("debugtext", kColorFrame); - dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem); + dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem, _render->m_debugFrameBuffer, _render->m_debugTextScale); BGFX_D3D11_PROFILER_END(); } m_deviceCtx->OMSetRenderTargets(1, s_zero.m_rtv, NULL); - if (NULL != m_msaaRt) - { - ID3D11Texture2D* backBufferColor; - DX_CHECK(m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBufferColor) ); - deviceCtx->ResolveSubresource(backBufferColor, 0, m_msaaRt, 0, m_scd.format); - DX_RELEASE(backBufferColor, 0); - } - if (_render->m_flush) { m_deviceCtx->Flush(); diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index b6b488a0e..f7983f6ed 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -353,7 +353,6 @@ namespace bgfx { namespace d3d11 void* create(const Memory* _mem, uint64_t _flags, uint8_t _skip, uint64_t _external); void destroy(); - void overrideInternal(uintptr_t _ptr, uint16_t _layerIndex); void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void clear(uint8_t _mip, uint8_t _numMips, uint16_t _layer, uint16_t _numLayers); void commit(uint8_t _stage, uint32_t _flags, const float _palette[][4], uint16_t _firstLayer = 0, uint16_t _numLayers = UINT16_MAX, uint8_t _firstMip = 0, uint8_t _numMips = UINT8_MAX, TextureDimension::Enum _dimension = TextureDimension::Count); @@ -392,11 +391,14 @@ namespace bgfx { namespace d3d11 uint8_t m_numMips; }; + constexpr uint16_t kMainFrameBufferIdx = BGFX_CONFIG_MAX_FRAME_BUFFERS; + struct FrameBufferD3D11 { FrameBufferD3D11() : m_dsv(NULL) , m_swapChain(NULL) + , m_msaaRt(NULL) , m_nwh(NULL) , m_width(0) , m_height(0) @@ -407,13 +409,18 @@ namespace bgfx { namespace d3d11 , m_needPresent(false) , m_needsQuadClear(false) { + bx::memSet(&m_desc, 0, sizeof(m_desc) ); bx::memSet(m_rtv, 0, sizeof(m_rtv) ); bx::memSet(m_uav, 0, sizeof(m_uav) ); bx::memSet(m_srv, 0, sizeof(m_srv) ); } void create(uint8_t _num, const Attachment* _attachment); - void create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat); + void create(uint16_t _denseIdx, const SwapChain& _desc); + void update(const SwapChain& _desc); + DxgiSwapChainDesc getSwapChainDesc() const; + void createSwapChainViews(); + void destroySwapChainViews(); uint16_t destroy(); void preReset(bool _force = false); void postReset(); @@ -422,11 +429,18 @@ namespace bgfx { namespace d3d11 void set(); HRESULT present(uint32_t _syncInterval, uint32_t _flags); + bool isSwapChain() const + { + return NULL != m_swapChain; + } + ID3D11RenderTargetView* m_rtv[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; ID3D11UnorderedAccessView* m_uav[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; ID3D11ShaderResourceView* m_srv[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; ID3D11DepthStencilView* m_dsv; Dxgi::SwapChainI* m_swapChain; + ID3D11Texture2D* m_msaaRt; + SwapChain m_desc; void* m_nwh; uint32_t m_width; uint32_t m_height; diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index a4c1f97d9..391610cff 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -320,19 +320,19 @@ namespace bgfx { namespace d3d12 }; static_assert(TextureFormat::Count == BX_COUNTOF(s_textureFormat) ); - static DXGI_FORMAT getBackBufferFormat(const Resolution& _resolution) + static DXGI_FORMAT getBackBufferDepthStencilFormat(const SwapChain& _swapChain) { - return 0 != (_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) - ? s_textureFormat[_resolution.formatColor].m_fmtSrgb - : s_textureFormat[_resolution.formatColor].m_fmt + return bimg::isDepth(bimg::TextureFormat::Enum(_swapChain.formatDepthStencil) ) + ? s_textureFormat[_swapChain.formatDepthStencil].m_fmtDsv + : DXGI_FORMAT_UNKNOWN ; } - static DXGI_FORMAT getBackBufferDepthStencilFormat(const Resolution& _resolution) + static DXGI_FORMAT getBackBufferFormat(const SwapChain& _desc) { - return bimg::isDepth(bimg::TextureFormat::Enum(_resolution.formatDepthStencil) ) - ? s_textureFormat[_resolution.formatDepthStencil].m_fmtDsv - : DXGI_FORMAT_UNKNOWN + return 0 != (_desc.flags & BGFX_SWAP_CHAIN_SRGB_BACKBUFFER) + ? s_textureFormat[_desc.formatColor].m_fmtSrgb + : s_textureFormat[_desc.formatColor].m_fmt ; } @@ -811,10 +811,10 @@ namespace bgfx { namespace d3d12 , m_renderDocDll(NULL) , m_winPixEvent(NULL) , m_featureLevel(D3D_FEATURE_LEVEL(0) ) - , m_swapChain(NULL) + , m_currentColor(NULL) , m_currentDepthStencil(NULL) - , m_backBufferDepthStencil(NULL) + , m_wireframe(false) , m_lost(false) , m_maxAnisotropy(1) @@ -884,7 +884,7 @@ namespace bgfx { namespace d3d12 m_fbh = BGFX_INVALID_HANDLE; bx::memSet(m_uniforms, 0, sizeof(m_uniforms) ); - bx::memSet(&m_resolution, 0, sizeof(m_resolution) ); + bx::memSet(&m_mainSwapChain, 0, sizeof(m_mainSwapChain) ); #if USE_D3D12_DYNAMIC_LIB @@ -1370,20 +1370,19 @@ namespace bgfx { namespace d3d12 m_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, m_cmd.m_commandQueue); errorState = ErrorState::CreatedCommandQueue; - if (NULL == g_platformData.backBuffer) { bx::memSet(&m_scd, 0, sizeof(m_scd) ); - m_scd.width = _init.resolution.width; - m_scd.height = _init.resolution.height; - m_scd.format = s_textureFormat[_init.resolution.formatColor].m_fmt; + m_scd.width = _init.swapChain.width; + m_scd.height = _init.swapChain.height; + m_scd.format = s_textureFormat[_init.swapChain.formatColor].m_fmt; m_scd.stereo = false; updateMsaa(m_scd.format); - m_scd.sampleDesc = s_msaa[(_init.resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; + m_scd.sampleDesc = s_msaa[(_init.swapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT]; m_scd.bufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - m_scd.bufferCount = bx::clamp(_init.resolution.numBackBuffers, 2, BX_COUNTOF(m_backBufferColor) ); - m_scd.scaling = 0 == g_platformData.ndt + m_scd.bufferCount = bx::clamp(_init.swapChain.numBackBuffers, 2, BGFX_CONFIG_MAX_BACK_BUFFERS ); + m_scd.scaling = 0 == _init.swapChain.ndt ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH ; @@ -1397,15 +1396,15 @@ namespace bgfx { namespace d3d12 m_scd.alphaMode = DXGI_ALPHA_MODE_IGNORE; m_scd.flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; - m_scd.maxFrameLatency = bx::min(_init.resolution.maxFrameLatency, BGFX_CONFIG_MAX_FRAME_LATENCY); + m_scd.maxFrameLatency = bx::min(_init.swapChain.maxFrameLatency, BGFX_CONFIG_MAX_FRAME_LATENCY); m_scd.waitable = false; - m_scd.nwh = g_platformData.nwh; - m_scd.ndt = g_platformData.ndt; + m_scd.nwh = _init.swapChain.nwh; + m_scd.ndt = _init.swapChain.ndt; m_scd.windowed = true; m_backBufferColorIdx = m_scd.bufferCount-1; - m_msaaRt = NULL; + mainFrameBuffer().m_msaaRt = NULL; if (NULL != m_scd.nwh) { @@ -1415,7 +1414,7 @@ namespace bgfx { namespace d3d12 hr = m_dxgi.createSwapChain( getDeviceForSwapChain() , m_scd - , &m_swapChain + , &mainFrameBuffer().m_swapChain ); #endif // BX_PLATFORM_LINUX @@ -1426,39 +1425,16 @@ namespace bgfx { namespace d3d12 } else { - m_resolution = _init.resolution; - m_resolution.reset = _init.resolution.reset & (~BGFX_RESET_INTERNAL_FORCE); + m_mainSwapChain = _init.swapChain; + m_reset = _init.reset & (~BGFX_RESET_INTERNAL_FORCE); - m_textVideoMem.resize(false, _init.resolution.width, _init.resolution.height); + m_textVideoMem.resize(false, _init.swapChain.width, _init.swapChain.height); m_textVideoMem.clear(); - } - if (1 < m_scd.sampleDesc.Count) - { - D3D12_RESOURCE_DESC resourceDesc; - resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - resourceDesc.Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT; - resourceDesc.Width = m_scd.width; - resourceDesc.Height = m_scd.height; - resourceDesc.MipLevels = 1; - resourceDesc.Format = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) - ? s_textureFormat[m_resolution.formatColor].m_fmtSrgb - : s_textureFormat[m_resolution.formatColor].m_fmt - ; - resourceDesc.SampleDesc = m_scd.sampleDesc; - resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - resourceDesc.DepthOrArraySize = 1; - - D3D12_CLEAR_VALUE clearValue; - clearValue.Format = resourceDesc.Format; - clearValue.Color[0] = 0.0f; - clearValue.Color[1] = 0.0f; - clearValue.Color[2] = 0.0f; - clearValue.Color[3] = 0.0f; - - m_msaaRt = createCommittedResource(m_device, HeapProperty::Texture, &resourceDesc, &clearValue, true); - setDebugObjectName(m_msaaRt, "MSAA Backbuffer"); + mainFrameBuffer().m_desc = m_mainSwapChain; + mainFrameBuffer().m_nwh = m_scd.nwh; + mainFrameBuffer().m_num = 1; + mainFrameBuffer().m_swapChainFormat = m_scd.format; } } } @@ -1466,8 +1442,8 @@ namespace bgfx { namespace d3d12 m_presentElapsed = 0; { - m_resolution.width = _init.resolution.width; - m_resolution.height = _init.resolution.height; + m_mainSwapChain.width = _init.swapChain.width; + m_mainSwapChain.height = _init.swapChain.height; m_windows[0] = BGFX_INVALID_HANDLE; m_numWindows = 1; @@ -1475,7 +1451,7 @@ namespace bgfx { namespace d3d12 #if BX_PLATFORM_WINDOWS m_infoQueue = NULL; - DX_CHECK(m_dxgi.m_factory->MakeWindowAssociation( (HWND)g_platformData.nwh + DX_CHECK(m_dxgi.m_factory->MakeWindowAssociation( (HWND)_init.swapChain.nwh , 0 | DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER @@ -1514,11 +1490,10 @@ namespace bgfx { namespace d3d12 } #endif // BX_PLATFORM_WINDOWS + static_assert(BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS >= BGFX_CONFIG_MAX_BACK_BUFFERS); + D3D12_DESCRIPTOR_HEAP_DESC rtvDescHeap; - rtvDescHeap.NumDescriptors = 0 - + BX_COUNTOF(m_backBufferColor) - + BGFX_CONFIG_MAX_FRAME_BUFFERS*BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS - ; + rtvDescHeap.NumDescriptors = (BGFX_CONFIG_MAX_FRAME_BUFFERS+1)*BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS; rtvDescHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; rtvDescHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; rtvDescHeap.NodeMask = 1; @@ -1528,10 +1503,7 @@ namespace bgfx { namespace d3d12 ) ); D3D12_DESCRIPTOR_HEAP_DESC dsvDescHeap; - dsvDescHeap.NumDescriptors = 0 - + 1 // reserved for depth backbuffer. - + BGFX_CONFIG_MAX_FRAME_BUFFERS - ; + dsvDescHeap.NumDescriptors = BGFX_CONFIG_MAX_FRAME_BUFFERS+1; dsvDescHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; dsvDescHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; dsvDescHeap.NodeMask = 1; @@ -2163,8 +2135,8 @@ namespace bgfx { namespace d3d12 DX_RELEASE(m_computeRootSignature, 0); DX_RELEASE(m_rootSignature, 0); - DX_RELEASE(m_msaaRt, 0); - DX_RELEASE(m_swapChain, 0); + DX_RELEASE(mainFrameBuffer().m_msaaRt, 0); + DX_RELEASE(mainFrameBuffer().m_swapChain, 0); m_device->SetPrivateDataInterface(IID_ID3D12CommandQueue, NULL); m_cmd.shutdown(); @@ -2348,7 +2320,7 @@ namespace bgfx { namespace d3d12 m_cmd.finish(m_backBufferColorFence[(m_backBufferColorIdx-1) % m_scd.bufferCount]); HRESULT hr = S_OK; - uint32_t syncInterval = !!(m_resolution.reset & BGFX_RESET_VSYNC); + uint32_t syncInterval = !!(m_reset & BGFX_RESET_VSYNC); uint32_t presentFlags = 0; #if !BX_PLATFORM_LINUX if (!syncInterval @@ -2364,10 +2336,13 @@ namespace bgfx { namespace d3d12 hr = frameBuffer.present(syncInterval, presentFlags); } + FrameBufferD3D12& mainFb = mainFrameBuffer(); + if (SUCCEEDED(hr) - && NULL != m_swapChain) + && mainFb.isSwapChain() ) { - hr = m_swapChain->Present(syncInterval, presentFlags); + mainFb.m_needPresent = true; + hr = mainFb.present(syncInterval, presentFlags); } const int64_t now = bx::getHPCounter(); @@ -2725,14 +2700,6 @@ namespace bgfx { namespace d3d12 release(mem); } - void overrideInternal(TextureHandle _handle, uintptr_t _ptr, uint16_t /*_layerIndex*/) override - { - // Resource ref. counts might be messed up outside of bgfx. - // Disabling ref. count check once texture is overridden. - setGraphicsDebuggerPresent(true); - m_textures[_handle.idx].overrideInternal(_ptr); - } - uintptr_t getInternal(TextureHandle _handle) override { setGraphicsDebuggerPresent(true); @@ -2749,7 +2716,7 @@ namespace bgfx { namespace d3d12 m_frameBuffers[_handle.idx].create(_num, _attachment); } - void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) override + void createFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override { finishAll(true); @@ -2757,7 +2724,7 @@ namespace bgfx { namespace d3d12 { FrameBufferHandle handle = m_windows[ii]; if (isValid(handle) - && m_frameBuffers[handle.idx].m_nwh == _nwh) + && m_frameBuffers[handle.idx].m_nwh == _desc.nwh) { destroyFrameBuffer(handle); } @@ -2765,7 +2732,22 @@ namespace bgfx { namespace d3d12 uint16_t denseIdx = m_numWindows++; m_windows[denseIdx] = _handle; - m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _format, _depthFormat); + m_frameBuffers[_handle.idx].create(denseIdx, _desc); + } + + void resizeFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override + { + m_frameBuffers[_handle.idx].update(_desc); + } + + DXGI_FORMAT getSwapChainDepthStencilFormat(const SwapChain& _desc) const + { + if (isValid(_desc.depth) ) + { + return s_textureFormat[m_textures[_desc.depth.idx].m_textureFormat].m_fmtDsv; + } + + return getBackBufferDepthStencilFormat(_desc); } void destroyFrameBuffer(FrameBufferHandle _handle) override @@ -2833,11 +2815,11 @@ namespace bgfx { namespace d3d12 swapIdx = uint8_t(swapFb->m_swapChain->GetCurrentBackBufferIndex() ); DX_CHECK(swapFb->m_swapChain->GetBuffer(swapIdx, IID_ID3D12Resource, (void**)&backBuffer) ); } - else if (NULL != m_swapChain) + else if (NULL != mainFrameBuffer().m_swapChain) { uint32_t idx = (m_backBufferColorIdx-1) % m_scd.bufferCount; m_cmd.finish(m_backBufferColorFence[idx]); - backBuffer = m_backBufferColor[idx]; + backBuffer = mainFrameBuffer().m_backBufferColor[idx]; } if (NULL == backBuffer) @@ -3001,12 +2983,13 @@ namespace bgfx { namespace d3d12 void submit(Frame* _render, const ClearQuad& _clearQuad, const MipGen& _mipGen, TextVideoMemBlitter& _textVideoMemBlitter) override; - void dbgTextRenderBegin(TextVideoMemBlitter& _blitter) override + void dbgTextRenderBegin(TextVideoMemBlitter& _blitter, FrameBufferHandle _handle) override { - const uint32_t width = m_scd.width; - const uint32_t height = m_scd.height; + const FrameBufferD3D12& frameBuffer = getFrameBuffer(_handle); + const uint32_t width = frameBuffer.m_width; + const uint32_t height = frameBuffer.m_height; - setFrameBuffer(BGFX_INVALID_HANDLE, false); + setFrameBuffer(_handle, false); D3D12_VIEWPORT vp; vp.TopLeftX = 0; @@ -3108,20 +3091,6 @@ namespace bgfx { namespace d3d12 { finishAll(); - if (NULL != m_swapChain) - { - for (uint32_t ii = 0, num = m_scd.bufferCount; ii < num; ++ii) - { -#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT - DX_RELEASE(m_backBufferColor[ii], num-1-ii); -#else - DX_RELEASE(m_backBufferColor[ii], 1); -#endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT - } - } - - DX_RELEASE(m_backBufferDepthStencil, 0); - for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) { m_frameBuffers[ii].preReset(); @@ -3136,111 +3105,15 @@ namespace bgfx { namespace d3d12 { bx::memSet(m_backBufferColorFence, 0, sizeof(m_backBufferColorFence) ); - uint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - - if (NULL != m_swapChain) - { - for (uint32_t ii = 0, num = m_scd.bufferCount; ii < num; ++ii) - { - D3D12_CPU_DESCRIPTOR_HANDLE handle = getCPUHandleHeapStart(m_rtvDescriptorHeap); - handle.ptr += ii * rtvDescriptorSize; - DX_CHECK(m_swapChain->GetBuffer(ii - , IID_ID3D12Resource - , (void**)&m_backBufferColor[ii] - ) ); - - D3D12_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = getBackBufferFormat(m_resolution); - - if (1 < getResourceDesc(m_backBufferColor[ii]).DepthOrArraySize) - { - rtvDesc.ViewDimension = (NULL == m_msaaRt) - ? D3D12_RTV_DIMENSION_TEXTURE2DARRAY - : D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY - ; - rtvDesc.Texture2DArray.FirstArraySlice = 0; - rtvDesc.Texture2DArray.ArraySize = getResourceDesc(m_backBufferColor[ii]).DepthOrArraySize; - rtvDesc.Texture2DArray.MipSlice = 0; - rtvDesc.Texture2DArray.PlaneSlice = 0; - } - else - { - rtvDesc.ViewDimension = (NULL == m_msaaRt) - ? D3D12_RTV_DIMENSION_TEXTURE2D - : D3D12_RTV_DIMENSION_TEXTURE2DMS - ; - rtvDesc.Texture2D.MipSlice = 0; - rtvDesc.Texture2D.PlaneSlice = 0; - } - - m_device->CreateRenderTargetView( - NULL == m_msaaRt - ? m_backBufferColor[ii] - : m_msaaRt - , &rtvDesc - , handle - ); - - if (BX_ENABLED(BX_PLATFORM_XBOXONE) ) - { - ID3D12Resource* resource = m_backBufferColor[ii]; - - BX_ASSERT(DXGI_FORMAT_R8G8B8A8_UNORM == m_scd.format, ""); - const uint32_t size = m_scd.width*m_scd.height*4; - - void* ptr; - DX_CHECK(resource->Map(0, NULL, &ptr) ); - bx::memSet(ptr, 0, size); - resource->Unmap(0, NULL); - } - } - } - m_commandList = m_cmd.alloc(); - if (bimg::isDepth(bimg::TextureFormat::Enum(m_resolution.formatDepthStencil) ) ) - { - D3D12_RESOURCE_DESC resourceDesc; - resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - resourceDesc.Alignment = 1 < m_scd.sampleDesc.Count ? D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT : 0; - resourceDesc.Width = bx::max(m_resolution.width, 1); - resourceDesc.Height = bx::max(m_resolution.height, 1); - resourceDesc.DepthOrArraySize = 1; - resourceDesc.MipLevels = 1; - resourceDesc.Format = s_textureFormat[m_resolution.formatDepthStencil].m_fmtDsv; - resourceDesc.SampleDesc = m_scd.sampleDesc; - resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; - - D3D12_CLEAR_VALUE clearValue; - clearValue.Format = resourceDesc.Format; - clearValue.DepthStencil.Depth = 1.0f; - clearValue.DepthStencil.Stencil = 0; - - m_backBufferDepthStencil = createCommittedResource(m_device, HeapProperty::Default, &resourceDesc, &clearValue); - m_device->CreateDepthStencilView(m_backBufferDepthStencil, NULL, getCPUHandleHeapStart(m_dsvDescriptorHeap) ); - - setResourceBarrier(m_commandList - , m_backBufferDepthStencil - , D3D12_RESOURCE_STATE_COMMON - , D3D12_RESOURCE_STATE_DEPTH_WRITE - ); - } + mainFrameBuffer().m_desc = m_mainSwapChain; for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) { m_frameBuffers[ii].postReset(); } - if (NULL != m_msaaRt) - { - setResourceBarrier(m_commandList - , m_msaaRt - , D3D12_RESOURCE_STATE_COMMON - , D3D12_RESOURCE_STATE_RESOLVE_SOURCE - ); - } - // capturePostReset(); } @@ -3288,9 +3161,9 @@ namespace bgfx { namespace d3d12 # endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT } - bool updateResolution(const Resolution& _resolution) + bool updateResolution(const SwapChain& _swapChain, uint32_t _reset) { - if (!!(_resolution.reset & BGFX_RESET_MAXANISOTROPY) ) + if (!!(_reset & BGFX_RESET_MAXANISOTROPY) ) { m_maxAnisotropy = D3D12_REQ_MAXANISOTROPY; } @@ -3299,7 +3172,7 @@ namespace bgfx { namespace d3d12 m_maxAnisotropy = 1; } - bool depthClamp = !!(_resolution.reset & BGFX_RESET_DEPTH_CLAMP); + bool depthClamp = !!(_reset & BGFX_RESET_DEPTH_CLAMP); if (m_depthClamp != depthClamp) { @@ -3308,10 +3181,10 @@ namespace bgfx { namespace d3d12 m_lastPso = NULL; } - if (_resolution.reset & BGFX_RESET_VSYNC) - m_resolution.reset |= BGFX_RESET_VSYNC; + if (_reset & BGFX_RESET_VSYNC) + m_reset |= BGFX_RESET_VSYNC; else - m_resolution.reset &= ~BGFX_RESET_VSYNC; + m_reset &= ~BGFX_RESET_VSYNC; const uint32_t maskFlags = ~(0 | BGFX_RESET_MAXANISOTROPY @@ -3320,56 +3193,53 @@ namespace bgfx { namespace d3d12 | BGFX_RESET_VSYNC ); - if (m_resolution.width != _resolution.width - || m_resolution.height != _resolution.height - || m_resolution.formatColor != _resolution.formatColor - || m_resolution.formatDepthStencil != _resolution.formatDepthStencil - || (m_resolution.reset&maskFlags) != (_resolution.reset&maskFlags) ) + if (m_mainSwapChain.width != _swapChain.width + || m_mainSwapChain.height != _swapChain.height + || m_mainSwapChain.formatColor != _swapChain.formatColor + || m_mainSwapChain.formatDepthStencil != _swapChain.formatDepthStencil + || m_mainSwapChain.nwh != _swapChain.nwh + || m_mainSwapChain.ndt != _swapChain.ndt + || (m_reset&maskFlags) != (_reset&maskFlags) ) { - uint32_t flags = _resolution.reset & (~BGFX_RESET_INTERNAL_FORCE); + uint32_t flags = _reset & (~BGFX_RESET_INTERNAL_FORCE); bool resize = true && BX_ENABLED(BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT) - && (m_resolution.reset&BGFX_RESET_MSAA_MASK) == (_resolution.reset&BGFX_RESET_MSAA_MASK) + && (m_mainSwapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK) == (_swapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK) ; - m_resolution = _resolution; - m_resolution.reset = flags; + m_mainSwapChain = _swapChain; + m_reset = flags; - m_textVideoMem.resize(false, _resolution.width, _resolution.height); + m_textVideoMem.resize(false, _swapChain.width, _swapChain.height); m_textVideoMem.clear(); - m_scd.width = _resolution.width; - m_scd.height = _resolution.height; - m_scd.format = s_textureFormat[_resolution.formatColor].m_fmt; + m_scd.width = _swapChain.width; + m_scd.height = _swapChain.height; + m_scd.format = s_textureFormat[_swapChain.formatColor].m_fmt; preReset(); - DX_RELEASE(m_msaaRt, 0); - - if (NULL == m_swapChain) - { - } - else + if (mainFrameBuffer().isSwapChain() ) { if (resize) { #if BX_PLATFORM_WINDOWS uint32_t nodeMask[] = { 1, 1, 1, 1 }; - static_assert(BX_COUNTOF(m_backBufferColor) == BX_COUNTOF(nodeMask) ); + static_assert(BGFX_CONFIG_MAX_BACK_BUFFERS == BX_COUNTOF(nodeMask) ); IUnknown* presentQueue[] ={ m_cmd.m_commandQueue, m_cmd.m_commandQueue, m_cmd.m_commandQueue, m_cmd.m_commandQueue }; - static_assert(BX_COUNTOF(m_backBufferColor) == BX_COUNTOF(presentQueue) ); - DX_CHECK(m_dxgi.resizeBuffers(m_swapChain, m_scd, nodeMask, presentQueue) ); + static_assert(BGFX_CONFIG_MAX_BACK_BUFFERS == BX_COUNTOF(presentQueue) ); + DX_CHECK(m_dxgi.resizeBuffers(mainFrameBuffer().m_swapChain, m_scd, nodeMask, presentQueue) ); #elif BX_PLATFORM_WINRT - DX_CHECK(m_dxgi.resizeBuffers(m_swapChain, m_scd) ); + DX_CHECK(m_dxgi.resizeBuffers(mainFrameBuffer().m_swapChain, m_scd) ); m_backBufferColorIdx = m_scd.bufferCount-1; #endif // BX_PLATFORM_WINDOWS } else { updateMsaa(m_scd.format); - m_scd.sampleDesc = s_msaa[(m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; + m_scd.sampleDesc = s_msaa[(m_mainSwapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT]; - DX_RELEASE(m_swapChain, 0); + DX_RELEASE(mainFrameBuffer().m_swapChain, 0); HRESULT hr; #if BX_PLATFORM_LINUX @@ -3378,39 +3248,13 @@ namespace bgfx { namespace d3d12 hr = m_dxgi.createSwapChain( getDeviceForSwapChain() , m_scd - , &m_swapChain + , &mainFrameBuffer().m_swapChain ); #endif // BX_PLATFORM_LINUX BGFX_FATAL(SUCCEEDED(hr), bgfx::Fatal::UnableToInitialize, "Failed to create swap chain."); } - if (1 < m_scd.sampleDesc.Count) - { - D3D12_RESOURCE_DESC resourceDesc; - resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - resourceDesc.Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT; - resourceDesc.Width = m_scd.width; - resourceDesc.Height = m_scd.height; - resourceDesc.MipLevels = 1; - resourceDesc.Format = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) - ? s_textureFormat[m_resolution.formatColor].m_fmtSrgb - : s_textureFormat[m_resolution.formatColor].m_fmt - ; - resourceDesc.SampleDesc = m_scd.sampleDesc; - resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - resourceDesc.DepthOrArraySize = 1; - - D3D12_CLEAR_VALUE clearValue; - clearValue.Format = resourceDesc.Format; - clearValue.Color[0] = 0.0f; - clearValue.Color[1] = 0.0f; - clearValue.Color[2] = 0.0f; - clearValue.Color[3] = 0.0f; - - m_msaaRt = createCommittedResource(m_device, HeapProperty::Texture, &resourceDesc, &clearValue, true); - setDebugObjectName(m_msaaRt, "MSAA Backbuffer"); - } + mainFrameBuffer().m_swapChainFormat = m_scd.format; } postReset(); @@ -3454,11 +3298,26 @@ namespace bgfx { namespace d3d12 _gpuAddress = sbo.buffer + sbo.offsets[0]; } + FrameBufferD3D12& getFrameBuffer(FrameBufferHandle _fbh) + { + return m_frameBuffers[isValid(_fbh) ? _fbh.idx : kMainFrameBufferIdx]; + } + + const FrameBufferD3D12& getFrameBuffer(FrameBufferHandle _fbh) const + { + return m_frameBuffers[isValid(_fbh) ? _fbh.idx : kMainFrameBufferIdx]; + } + + FrameBufferD3D12& mainFrameBuffer() + { + return m_frameBuffers[kMainFrameBufferIdx]; + } + D3D12_CPU_DESCRIPTOR_HANDLE getRtv(FrameBufferHandle _fbh) { - FrameBufferD3D12& frameBuffer = m_frameBuffers[_fbh.idx]; + FrameBufferD3D12& frameBuffer = getFrameBuffer(_fbh); - if (NULL != frameBuffer.m_swapChain) + if (frameBuffer.isSwapChain() ) { #if BX_PLATFORM_WINDOWS uint8_t idx = uint8_t(frameBuffer.m_swapChain->GetCurrentBackBufferIndex() ); @@ -3472,20 +3331,22 @@ namespace bgfx { namespace d3d12 D3D12_CPU_DESCRIPTOR_HANDLE getRtv(FrameBufferHandle _fbh, uint8_t _attachment) { + const uint16_t idx = isValid(_fbh) ? _fbh.idx : kMainFrameBufferIdx; D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = getCPUHandleHeapStart(m_rtvDescriptorHeap); uint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); D3D12_CPU_DESCRIPTOR_HANDLE result = { - rtvDescriptor.ptr + (BX_COUNTOF(m_backBufferColor) + _fbh.idx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS + _attachment) * rtvDescriptorSize + rtvDescriptor.ptr + (idx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS + _attachment) * rtvDescriptorSize }; return result; } D3D12_CPU_DESCRIPTOR_HANDLE getDsv(FrameBufferHandle _fbh) const { + const uint16_t idx = isValid(_fbh) ? _fbh.idx : kMainFrameBufferIdx; D3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = getCPUHandleHeapStart(m_dsvDescriptorHeap); uint32_t dsvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); - D3D12_CPU_DESCRIPTOR_HANDLE result = { dsvDescriptor.ptr + (1 + _fbh.idx) * dsvDescriptorSize }; + D3D12_CPU_DESCRIPTOR_HANDLE result = { dsvDescriptor.ptr + idx * dsvDescriptorSize }; return result; } @@ -3528,19 +3389,28 @@ namespace bgfx { namespace d3d12 } } } + else if (isValid(frameBuffer.m_desc.depth) ) + { + TextureD3D12& texture = m_textures[frameBuffer.m_desc.depth.idx]; + const bool writeOnly = 0 != (texture.m_flags&BGFX_TEXTURE_RT_WRITE_ONLY); + if (!writeOnly) + { + texture.setState(m_commandList, D3D12_RESOURCE_STATE_DEPTH_READ); + } + } } if (!isValid(_fbh) ) { - if (NULL != m_swapChain) + FrameBufferD3D12& frameBuffer = getFrameBuffer(_fbh); + + if (frameBuffer.isSwapChain() ) { - m_rtvHandle = getCPUHandleHeapStart(m_rtvDescriptorHeap); - const uint32_t rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - m_rtvHandle.ptr += m_backBufferColorIdx * rtvDescriptorSize; - m_dsvHandle = getCPUHandleHeapStart(m_dsvDescriptorHeap); + m_rtvHandle = getRtv(_fbh, uint8_t(m_backBufferColorIdx) ); + m_dsvHandle = getDsv(_fbh); m_currentColor = &m_rtvHandle; - m_currentDepthStencil = NULL != m_backBufferDepthStencil + m_currentDepthStencil = NULL != frameBuffer.m_backBufferDepthStencil ? &m_dsvHandle : NULL ; @@ -3567,7 +3437,13 @@ namespace bgfx { namespace d3d12 m_currentColor = NULL; } - if (isValid(frameBuffer.m_depth) ) + const bool swapChainDepth = true + && NULL != frameBuffer.m_swapChain + && (NULL != frameBuffer.m_backBufferDepthStencil || isValid(frameBuffer.m_desc.depth) ) + ; + + if (isValid(frameBuffer.m_depth) + || swapChainDepth) { m_dsvHandle = getDsv(_fbh); m_currentDepthStencil = &m_dsvHandle; @@ -3580,6 +3456,12 @@ namespace bgfx { namespace d3d12 if (NULL != frameBuffer.m_swapChain) { frameBuffer.m_needPresent = true; + + if (isValid(frameBuffer.m_desc.depth) ) + { + TextureD3D12& texture = m_textures[frameBuffer.m_desc.depth.idx]; + texture.setState(m_commandList, D3D12_RESOURCE_STATE_DEPTH_WRITE); + } } else { @@ -4026,12 +3908,14 @@ namespace bgfx { namespace d3d12 else { murmur.add(frameBuffer.m_swapChainFormat); + murmur.add(getSwapChainDepthStencilFormat(frameBuffer.m_desc) ); + murmur.add(frameBuffer.getSwapChainDesc().sampleDesc); } } else { - murmur.add(getBackBufferFormat(m_resolution) ); - murmur.add(getBackBufferDepthStencilFormat(m_resolution) ); + murmur.add(getBackBufferFormat(m_mainSwapChain) ); + murmur.add(getBackBufferDepthStencilFormat(m_mainSwapChain) ); } murmur.add(_numInstanceData); @@ -4133,14 +4017,14 @@ namespace bgfx { namespace d3d12 { desc.NumRenderTargets = 1; desc.RTVFormats[0] = frameBuffer.m_swapChainFormat; - desc.DSVFormat = DXGI_FORMAT_UNKNOWN; + desc.DSVFormat = getSwapChainDepthStencilFormat(frameBuffer.m_desc); } } else { desc.NumRenderTargets = 1; - desc.RTVFormats[0] = getBackBufferFormat(m_resolution); - desc.DSVFormat = getBackBufferDepthStencilFormat(m_resolution); + desc.RTVFormats[0] = getBackBufferFormat(m_mainSwapChain); + desc.DSVFormat = getBackBufferDepthStencilFormat(m_mainSwapChain); } desc.SampleDesc = m_scd.sampleDesc; @@ -4149,8 +4033,13 @@ namespace bgfx { namespace d3d12 { const FrameBufferD3D12& frameBuffer = m_frameBuffers[m_fbh.idx]; - if (NULL == frameBuffer.m_swapChain - && 0 < frameBuffer.m_num) + if (NULL != frameBuffer.m_swapChain) + { + // A window swap chain has its own sample count + // (BGFX_SWAP_CHAIN_MSAA_*), not main's. + desc.SampleDesc = frameBuffer.getSwapChainDesc().sampleDesc; + } + else if (0 < frameBuffer.m_num) { const uint64_t flags = m_textures[frameBuffer.m_texture[0].idx].m_flags; const uint32_t msaaQuality = bx::satSub(uint32_t( (flags & BGFX_TEXTURE_RT_MSAA_MASK) >> BGFX_TEXTURE_RT_MSAA_SHIFT), 1u); @@ -4494,9 +4383,6 @@ namespace bgfx { namespace d3d12 D3D12_FEATURE_DATA_ARCHITECTURE m_architecture; D3D12_FEATURE_DATA_D3D12_OPTIONS m_options; - Dxgi::SwapChainI* m_swapChain; - ID3D12Resource* m_msaaRt; - #if BX_PLATFORM_WINDOWS ID3D12InfoQueue* m_infoQueue; #endif // BX_PLATFORM_WINDOWS @@ -4518,9 +4404,9 @@ namespace bgfx { namespace d3d12 D3D12_CPU_DESCRIPTOR_HANDLE m_dsvHandle; D3D12_CPU_DESCRIPTOR_HANDLE* m_currentColor; D3D12_CPU_DESCRIPTOR_HANDLE* m_currentDepthStencil; - ID3D12Resource* m_backBufferColor[BGFX_CONFIG_MAX_BACK_BUFFERS]; + uint64_t m_backBufferColorFence[BGFX_CONFIG_MAX_BACK_BUFFERS]; - ID3D12Resource* m_backBufferDepthStencil; + ScratchBufferD3D12 m_scratchBuffer[BGFX_CONFIG_MAX_BACK_BUFFERS]; ChunkedScratchBufferD3D12 m_uniformScratchBuffer; @@ -4534,11 +4420,12 @@ namespace bgfx { namespace d3d12 BatchD3D12 m_batch; ID3D12GraphicsCommandList* m_commandList; - Resolution m_resolution; + SwapChain m_mainSwapChain; + uint32_t m_reset; bool m_wireframe; bool m_lost; - SwapChainDesc m_scd; + DxgiSwapChainDesc m_scd; uint32_t m_maxAnisotropy; bool m_depthClamp; @@ -4548,7 +4435,7 @@ namespace bgfx { namespace d3d12 ProgramD3D12 m_program[BGFX_CONFIG_MAX_PROGRAMS]; TextureD3D12 m_textures[BGFX_CONFIG_MAX_TEXTURES]; VertexLayout m_vertexLayouts[BGFX_CONFIG_MAX_VERTEX_LAYOUTS]; - FrameBufferD3D12 m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS]; + FrameBufferD3D12 m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS+1]; void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS]; Matrix4 m_predefinedUniforms[PredefinedUniform::Count]; UniformRegistry m_uniformReg; @@ -7028,13 +6915,6 @@ namespace bgfx { namespace d3d12 } } - void TextureD3D12::overrideInternal(uintptr_t _ptr) - { - destroy(); - m_flags |= BGFX_SAMPLER_INTERNAL_SHARED; - m_ptr = (ID3D12Resource*)_ptr; - } - void TextureD3D12::clear(ID3D12GraphicsCommandList* _commandList, uint8_t _mip, uint8_t _numMips, uint16_t _layer, uint16_t _numLayers) { const D3D12_RESOURCE_STATES saved = setState(_commandList, D3D12_RESOURCE_STATE_COPY_DEST); @@ -7534,19 +7414,30 @@ namespace bgfx { namespace d3d12 postReset(); } - void FrameBufferD3D12::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) + DxgiSwapChainDesc FrameBufferD3D12::getSwapChainDesc() const { - BX_UNUSED(_nwh, _width, _height, _format, _depthFormat); + DxgiSwapChainDesc scd; + bx::memCopy(&scd, &s_renderD3D12->m_scd, sizeof(DxgiSwapChainDesc) ); + scd.format = s_textureFormat[m_desc.formatColor].m_fmt; + scd.width = m_desc.width; + scd.height = m_desc.height; + scd.nwh = m_desc.nwh; + scd.ndt = m_desc.ndt; + scd.sampleDesc = s_msaa[(m_desc.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT]; + scd.waitable = true; + + return scd; + } + + void FrameBufferD3D12::create(uint16_t _denseIdx, const SwapChain& _desc) + { + m_desc = _desc; + m_nwh = _desc.nwh; + m_denseIdx = _denseIdx; + m_num = 1; #if BX_PLATFORM_WINDOWS - SwapChainDesc scd; - bx::memCopy(&scd, &s_renderD3D12->m_scd, sizeof(SwapChainDesc) ); - scd.format = TextureFormat::Count == _format ? scd.format : s_textureFormat[_format].m_fmt; - scd.width = _width; - scd.height = _height; - scd.nwh = _nwh; - scd.sampleDesc = s_msaa[0]; - scd.waitable = true; + const DxgiSwapChainDesc scd = getSwapChainDesc(); HRESULT hr; hr = s_renderD3D12->m_dxgi.createSwapChain( @@ -7555,6 +7446,14 @@ namespace bgfx { namespace d3d12 , &m_swapChain ); BGFX_FATAL(SUCCEEDED(hr), Fatal::UnableToInitialize, "Failed to create swap chain."); + + if (FAILED(hr) ) + { + m_swapChain = NULL; + m_num = 0; + return; + } + m_state = D3D12_RESOURCE_STATE_PRESENT; m_swapChainFormat = scd.format; @@ -7565,32 +7464,232 @@ namespace bgfx { namespace d3d12 } DX_CHECK(s_renderD3D12->m_dxgi.m_factory->MakeWindowAssociation( - (HWND)_nwh + (HWND)_desc.nwh , 0 | DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER ) ); + createSwapChainViews(); +#endif // BX_PLATFORM_WINDOWS + } + + void FrameBufferD3D12::update(const SwapChain& _desc) + { + if (!isSwapChain() ) + { + create(m_denseIdx, _desc); + return; + } + + m_desc = _desc; + m_nwh = _desc.nwh; + +#if BX_PLATFORM_WINDOWS + const DxgiSwapChainDesc scd = getSwapChainDesc(); + + s_renderD3D12->finishAll(true); + + destroySwapChainViews(); + + uint32_t nodeMask[] = { 1, 1, 1, 1 }; + IUnknown* presentQueue[] = + { + s_renderD3D12->m_cmd.m_commandQueue, + s_renderD3D12->m_cmd.m_commandQueue, + s_renderD3D12->m_cmd.m_commandQueue, + s_renderD3D12->m_cmd.m_commandQueue, + }; + static_assert(BX_COUNTOF(nodeMask) == BX_COUNTOF(presentQueue) ); + + DX_CHECK(s_renderD3D12->m_dxgi.resizeBuffers(m_swapChain, scd, nodeMask, presentQueue) ); + + m_state = D3D12_RESOURCE_STATE_PRESENT; + m_swapChainFormat = scd.format; + + createSwapChainViews(); +#endif // BX_PLATFORM_WINDOWS + } + + void FrameBufferD3D12::createSwapChainViews() + { +#if BX_PLATFORM_WINDOWS ID3D12Device* device = s_renderD3D12->m_device; - FrameBufferHandle fbh = { uint16_t(this - s_renderD3D12->m_frameBuffers) }; + + const FrameBufferHandle fbh = { uint16_t(this - s_renderD3D12->m_frameBuffers) }; + const DxgiSwapChainDesc scd = getSwapChainDesc(); + + if (1 < scd.sampleDesc.Count + && NULL == m_msaaRt) + { + D3D12_RESOURCE_DESC resourceDesc; + resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + resourceDesc.Alignment = D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT; + resourceDesc.Width = scd.width; + resourceDesc.Height = scd.height; + resourceDesc.MipLevels = 1; + resourceDesc.Format = (m_desc.flags & BGFX_SWAP_CHAIN_SRGB_BACKBUFFER) + ? s_textureFormat[m_desc.formatColor].m_fmtSrgb + : s_textureFormat[m_desc.formatColor].m_fmt + ; + resourceDesc.SampleDesc = scd.sampleDesc; + resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + resourceDesc.DepthOrArraySize = 1; + + D3D12_CLEAR_VALUE clearValue; + clearValue.Format = resourceDesc.Format; + clearValue.Color[0] = 0.0f; + clearValue.Color[1] = 0.0f; + clearValue.Color[2] = 0.0f; + clearValue.Color[3] = 0.0f; + + m_msaaRt = createCommittedResource(device, HeapProperty::Texture, &resourceDesc, &clearValue, true); + setDebugObjectName(m_msaaRt, "MSAA Backbuffer"); + } for (uint32_t ii = 0, num = scd.bufferCount; ii < num; ++ii) { - D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = s_renderD3D12->getRtv(fbh, uint8_t(ii) ); + const D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = s_renderD3D12->getRtv(fbh, uint8_t(ii) ); - ID3D12Resource* colorBuffer; DX_CHECK(m_swapChain->GetBuffer(ii , IID_ID3D12Resource - , (void**)&colorBuffer + , (void**)&m_backBufferColor[ii] ) ); - device->CreateRenderTargetView(colorBuffer, NULL, rtvHandle); - DX_RELEASE(colorBuffer, 0); - } -#endif // BX_PLATFORM_WINDOWS - m_nwh = _nwh; - m_denseIdx = _denseIdx; - m_num = 1; + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = getBackBufferFormat(m_desc); + + if (1 < getResourceDesc(m_backBufferColor[ii]).DepthOrArraySize) + { + rtvDesc.ViewDimension = (NULL == m_msaaRt) + ? D3D12_RTV_DIMENSION_TEXTURE2DARRAY + : D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY + ; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = getResourceDesc(m_backBufferColor[ii]).DepthOrArraySize; + rtvDesc.Texture2DArray.MipSlice = 0; + rtvDesc.Texture2DArray.PlaneSlice = 0; + } + else + { + rtvDesc.ViewDimension = (NULL == m_msaaRt) + ? D3D12_RTV_DIMENSION_TEXTURE2D + : D3D12_RTV_DIMENSION_TEXTURE2DMS + ; + rtvDesc.Texture2D.MipSlice = 0; + rtvDesc.Texture2D.PlaneSlice = 0; + } + + device->CreateRenderTargetView( + NULL == m_msaaRt ? m_backBufferColor[ii] : m_msaaRt + , &rtvDesc + , rtvHandle + ); + + if (BX_ENABLED(BX_PLATFORM_XBOXONE) ) + { + ID3D12Resource* resource = m_backBufferColor[ii]; + + BX_ASSERT(DXGI_FORMAT_R8G8B8A8_UNORM == scd.format, ""); + const uint32_t size = scd.width*scd.height*4; + + void* ptr; + DX_CHECK(resource->Map(0, NULL, &ptr) ); + bx::memSet(ptr, 0, size); + resource->Unmap(0, NULL); + } + } + + if (isValid(m_desc.depth) ) + { + const TextureD3D12& texture = s_renderD3D12->m_textures[m_desc.depth.idx]; + + D3D12_DEPTH_STENCIL_VIEW_DESC dsvd; + dsvd.Format = s_textureFormat[texture.m_textureFormat].m_fmtDsv; + dsvd.ViewDimension = 1 < scd.sampleDesc.Count + ? D3D12_DSV_DIMENSION_TEXTURE2DMS + : D3D12_DSV_DIMENSION_TEXTURE2D + ; + dsvd.Flags = D3D12_DSV_FLAG_NONE; + dsvd.Texture2D.MipSlice = 0; + + device->CreateDepthStencilView(texture.m_ptr, &dsvd, s_renderD3D12->getDsv(fbh) ); + } + else if (bimg::isDepth(bimg::TextureFormat::Enum(m_desc.formatDepthStencil) ) ) + { + D3D12_RESOURCE_DESC resourceDesc; + resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + resourceDesc.Alignment = 1 < scd.sampleDesc.Count ? D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT : 0; + resourceDesc.Width = bx::max(scd.width, 1); + resourceDesc.Height = bx::max(scd.height, 1); + resourceDesc.DepthOrArraySize = 1; + resourceDesc.MipLevels = 1; + resourceDesc.Format = s_textureFormat[m_desc.formatDepthStencil].m_fmtDsv; + resourceDesc.SampleDesc = scd.sampleDesc; + resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + + D3D12_CLEAR_VALUE clearValue; + clearValue.Format = resourceDesc.Format; + clearValue.DepthStencil.Depth = 1.0f; + clearValue.DepthStencil.Stencil = 0; + + m_backBufferDepthStencil = createCommittedResource(device, HeapProperty::Default, &resourceDesc, &clearValue); + device->CreateDepthStencilView(m_backBufferDepthStencil, NULL, s_renderD3D12->getDsv(fbh) ); + + setResourceBarrier(s_renderD3D12->m_commandList + , m_backBufferDepthStencil + , D3D12_RESOURCE_STATE_COMMON + , D3D12_RESOURCE_STATE_DEPTH_WRITE + ); + + // A fresh depth resource holds undefined contents and undefined + // compression metadata; the first view may load rather than clear it. + s_renderD3D12->m_commandList->ClearDepthStencilView( + s_renderD3D12->getDsv(fbh) + , D3D12_CLEAR_FLAGS(D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL) + , clearValue.DepthStencil.Depth + , clearValue.DepthStencil.Stencil + , 0 + , NULL + ); + } + + if (NULL != m_msaaRt) + { + setResourceBarrier(s_renderD3D12->m_commandList + , m_msaaRt + , D3D12_RESOURCE_STATE_COMMON + , D3D12_RESOURCE_STATE_RESOLVE_SOURCE + ); + } + + m_width = scd.width; + m_height = scd.height; +#endif // BX_PLATFORM_WINDOWS + } + + void FrameBufferD3D12::destroySwapChainViews() + { +#if BX_PLATFORM_WINDOWS + const uint32_t num = getSwapChainDesc().bufferCount; + + for (uint32_t ii = 0; ii < num; ++ii) + { + if (NULL != m_backBufferColor[ii]) + { +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT + DX_RELEASE(m_backBufferColor[ii], num-1-ii); +#else + DX_RELEASE(m_backBufferColor[ii], 1); +#endif // BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT + } + } + + DX_RELEASE(m_backBufferDepthStencil, 0); + DX_RELEASE(m_msaaRt, 0); +#endif // BX_PLATFORM_WINDOWS } uint16_t FrameBufferD3D12::destroy() @@ -7603,6 +7702,11 @@ namespace bgfx { namespace d3d12 } #endif // !BX_PLATFORM_LINUX + if (isSwapChain() ) + { + destroySwapChainViews(); + } + DX_RELEASE(m_swapChain, 0); m_swapChainFormat = DXGI_FORMAT_UNKNOWN; @@ -7642,10 +7746,22 @@ namespace bgfx { namespace d3d12 void FrameBufferD3D12::preReset() { + if (isSwapChain() ) + { + destroySwapChainViews(); + m_needPresent = false; + } } void FrameBufferD3D12::postReset() { + if (isSwapChain() ) + { + createSwapChainViews(); + + return; + } + if (m_numTh != 0) { ID3D12Device* device = s_renderD3D12->m_device; @@ -7653,7 +7769,7 @@ namespace bgfx { namespace d3d12 D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor = getCPUHandleHeapStart(s_renderD3D12->m_rtvDescriptorHeap); uint32_t rtvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); uint32_t fbhIdx = (uint32_t)(this - s_renderD3D12->m_frameBuffers); - rtvDescriptor.ptr += (BX_COUNTOF(s_renderD3D12->m_backBufferColor) + fbhIdx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) * rtvDescriptorSize; + rtvDescriptor.ptr += fbhIdx * BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS * rtvDescriptorSize; m_width = 0; m_height = 0; @@ -7683,7 +7799,7 @@ namespace bgfx { namespace d3d12 m_depth = at.handle; D3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = getCPUHandleHeapStart(s_renderD3D12->m_dsvDescriptorHeap); uint32_t dsvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); - dsvDescriptor.ptr += (1 + fbhIdx) * dsvDescriptorSize; + dsvDescriptor.ptr += fbhIdx * dsvDescriptorSize; const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(texture.m_textureFormat) ); BX_UNUSED(blockInfo); @@ -7902,12 +8018,15 @@ namespace bgfx { namespace d3d12 } } - if (isValid(m_depth) - && (BGFX_CLEAR_DEPTH|BGFX_CLEAR_STENCIL) & _clear.m_flags) + const bool swapChainDepth = true + && isSwapChain() + && (NULL != m_backBufferDepthStencil || isValid(m_desc.depth) ) + ; + + if ( (isValid(m_depth) || swapChainDepth) + && (BGFX_CLEAR_DEPTH|BGFX_CLEAR_STENCIL) & _clear.m_flags) { - D3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = getCPUHandleHeapStart(s_renderD3D12->m_dsvDescriptorHeap); - uint32_t dsvDescriptorSize = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV); - dsvDescriptor.ptr += (1 + fbh.idx) * dsvDescriptorSize; + D3D12_CPU_DESCRIPTOR_HANDLE dsvDescriptor = s_renderD3D12->getDsv(fbh); DWORD flags = 0; flags |= (_clear.m_flags & BGFX_CLEAR_DEPTH) ? D3D12_CLEAR_FLAG_DEPTH : 0; @@ -8854,7 +8973,7 @@ namespace bgfx { namespace d3d12 { m_mipGen = &_mipGen; if (m_lost - || updateResolution(_render->m_resolution) ) + || updateResolution(_render->m_mainSwapChain, _render->m_reset) ) { return; } @@ -8942,9 +9061,9 @@ namespace bgfx { namespace d3d12 ); #if BX_PLATFORM_WINDOWS - if (NULL != m_swapChain) + if (NULL != mainFrameBuffer().m_swapChain) { - m_backBufferColorIdx = m_swapChain->GetCurrentBackBufferIndex(); + m_backBufferColorIdx = mainFrameBuffer().m_swapChain->GetCurrentBackBufferIndex(); } else { @@ -8978,24 +9097,24 @@ namespace bgfx { namespace d3d12 bx::memSet(bindState, kBindStateNotBuilt, numRenderBinds); uint32_t bindCacheCount = 0; - if (NULL != m_msaaRt) + if (NULL != mainFrameBuffer().m_msaaRt) { setResourceBarrier(m_commandList - , m_msaaRt + , mainFrameBuffer().m_msaaRt , D3D12_RESOURCE_STATE_RESOLVE_SOURCE , D3D12_RESOURCE_STATE_RENDER_TARGET ); setResourceBarrier(m_commandList - , m_backBufferColor[m_backBufferColorIdx] + , mainFrameBuffer().m_backBufferColor[m_backBufferColorIdx] , D3D12_RESOURCE_STATE_PRESENT , D3D12_RESOURCE_STATE_RESOLVE_DEST ); } - else if (NULL != m_swapChain) + else if (NULL != mainFrameBuffer().m_swapChain) { setResourceBarrier(m_commandList - , m_backBufferColor[m_backBufferColorIdx] + , mainFrameBuffer().m_backBufferColor[m_backBufferColorIdx] , D3D12_RESOURCE_STATE_PRESENT , D3D12_RESOURCE_STATE_RENDER_TARGET ); @@ -9833,7 +9952,7 @@ namespace bgfx { namespace d3d12 if (0 < _render->m_numRenderItems) { - if (0 != (m_resolution.reset & BGFX_RESET_FLUSH_AFTER_RENDER) ) + if (0 != (m_reset & BGFX_RESET_FLUSH_AFTER_RENDER) ) { // deviceCtx->Flush(); } @@ -10007,12 +10126,12 @@ namespace bgfx { namespace d3d12 , double(presentMax)*toMs ); - const uint32_t msaa = (m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + const uint32_t msaa = (m_mainSwapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT; tvm.printf(10, pos++, 0x8b, " Reset flags: [%c] vsync, [%c] MSAAx%d, [%c] MaxAnisotropy " - , !!(m_resolution.reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' + , !!(m_reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' , 0 != msaa ? '\xfe' : ' ' , 1<m_debugFrameBuffer, _render->m_debugTextScale); BGFX_D3D12_PROFILER_END(); } @@ -10105,33 +10224,33 @@ namespace bgfx { namespace d3d12 { BGFX_D3D12_PROFILER_BEGIN_LITERAL("debugtext", kColorFrame); - dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem); + dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem, _render->m_debugFrameBuffer, _render->m_debugTextScale); BGFX_D3D12_PROFILER_END(); } m_commandList->OMSetRenderTargets(0, NULL, false, NULL); - if (NULL != m_msaaRt) + if (NULL != mainFrameBuffer().m_msaaRt) { setResourceBarrier(m_commandList - , m_msaaRt + , mainFrameBuffer().m_msaaRt , D3D12_RESOURCE_STATE_RENDER_TARGET , D3D12_RESOURCE_STATE_RESOLVE_SOURCE ); - m_commandList->ResolveSubresource(m_backBufferColor[m_backBufferColorIdx], 0, m_msaaRt, 0, m_scd.format); + m_commandList->ResolveSubresource(mainFrameBuffer().m_backBufferColor[m_backBufferColorIdx], 0, mainFrameBuffer().m_msaaRt, 0, m_scd.format); setResourceBarrier(m_commandList - , m_backBufferColor[m_backBufferColorIdx] + , mainFrameBuffer().m_backBufferColor[m_backBufferColorIdx] , D3D12_RESOURCE_STATE_RESOLVE_DEST , D3D12_RESOURCE_STATE_PRESENT ); } - else if (NULL != m_swapChain) + else if (NULL != mainFrameBuffer().m_swapChain) { setResourceBarrier(m_commandList - , m_backBufferColor[m_backBufferColorIdx] + , mainFrameBuffer().m_backBufferColor[m_backBufferColorIdx] , D3D12_RESOURCE_STATE_RENDER_TARGET , D3D12_RESOURCE_STATE_PRESENT ); @@ -10144,6 +10263,32 @@ namespace bgfx { namespace d3d12 if (NULL != frameBuffer.m_swapChain) { uint8_t idx = uint8_t(frameBuffer.m_swapChain->GetCurrentBackBufferIndex() ); + + if (NULL != frameBuffer.m_msaaRt) + { + setResourceBarrier(m_commandList + , frameBuffer.m_msaaRt + , D3D12_RESOURCE_STATE_RENDER_TARGET + , D3D12_RESOURCE_STATE_RESOLVE_SOURCE + ); + + frameBuffer.setState(m_commandList, idx, D3D12_RESOURCE_STATE_RESOLVE_DEST); + + m_commandList->ResolveSubresource( + frameBuffer.m_backBufferColor[idx] + , 0 + , frameBuffer.m_msaaRt + , 0 + , frameBuffer.getSwapChainDesc().format + ); + + setResourceBarrier(m_commandList + , frameBuffer.m_msaaRt + , D3D12_RESOURCE_STATE_RESOLVE_SOURCE + , D3D12_RESOURCE_STATE_RENDER_TARGET + ); + } + frameBuffer.setState(m_commandList, idx, D3D12_RESOURCE_STATE_PRESENT); } } diff --git a/src/renderer_d3d12.h b/src/renderer_d3d12.h index 0fa45ae08..834e01c1b 100644 --- a/src/renderer_d3d12.h +++ b/src/renderer_d3d12.h @@ -451,7 +451,6 @@ namespace bgfx { namespace d3d12 void* create(const Memory* _mem, uint64_t _flags, uint8_t _skip, uint64_t _external); void destroy(); - void overrideInternal(uintptr_t _ptr); void clear(ID3D12GraphicsCommandList* _commandList, uint8_t _mip, uint8_t _numMips, uint16_t _layer, uint16_t _numLayers); void update(ID3D12GraphicsCommandList* _commandList, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void resolve(ID3D12GraphicsCommandList* _commandList, uint8_t _resolve, uint32_t _layer, uint32_t _numLayers, uint32_t _mip); @@ -479,11 +478,15 @@ namespace bgfx { namespace d3d12 VideoDecoderD3D12* m_videoDecoder; }; + constexpr uint16_t kMainFrameBufferIdx = BGFX_CONFIG_MAX_FRAME_BUFFERS; + struct FrameBufferD3D12 { FrameBufferD3D12() : m_swapChain(NULL) , m_swapChainFormat(DXGI_FORMAT_UNKNOWN) + , m_msaaRt(NULL) + , m_backBufferDepthStencil(NULL) , m_nwh(NULL) , m_width(0) , m_height(0) @@ -495,10 +498,16 @@ namespace bgfx { namespace d3d12 , m_frameLatencyWaitableObject(NULL) { m_depth.idx = bgfx::kInvalidHandle; + bx::memSet(&m_desc, 0, sizeof(m_desc) ); + bx::memSet(m_backBufferColor, 0, sizeof(m_backBufferColor) ); } void create(uint8_t _num, const Attachment* _attachment); - void create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat); + void create(uint16_t _denseIdx, const SwapChain& _desc); + void update(const SwapChain& _desc); + DxgiSwapChainDesc getSwapChainDesc() const; + void createSwapChainViews(); + void destroySwapChainViews(); uint16_t destroy(); HRESULT present(uint32_t _syncInterval, uint32_t _flags); void preReset(); @@ -507,10 +516,19 @@ namespace bgfx { namespace d3d12 void clear(ID3D12GraphicsCommandList* _commandList, const Clear& _clear, const float _palette[][4], const D3D12_RECT* _rect = NULL, uint32_t _num = 0); D3D12_RESOURCE_STATES setState(ID3D12GraphicsCommandList* _commandList, uint8_t _idx, D3D12_RESOURCE_STATES _state); + bool isSwapChain() const + { + return NULL != m_swapChain; + } + TextureHandle m_texture[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; TextureHandle m_depth; Dxgi::SwapChainI* m_swapChain; DXGI_FORMAT m_swapChainFormat; + SwapChain m_desc; + ID3D12Resource* m_backBufferColor[BGFX_CONFIG_MAX_BACK_BUFFERS]; + ID3D12Resource* m_msaaRt; + ID3D12Resource* m_backBufferDepthStencil; void* m_nwh; uint32_t m_width; uint32_t m_height; diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 397a6c23a..1f84fa79f 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -2270,9 +2270,11 @@ namespace bgfx { namespace gl m_fbh = BGFX_INVALID_HANDLE; bx::memSet(m_uniforms, 0, sizeof(m_uniforms) ); - bx::memSet(&m_resolution, 0, sizeof(m_resolution) ); + bx::memSet(&m_mainSwapChain, 0, sizeof(m_mainSwapChain) ); - setRenderContextSize(_init.resolution); + m_reset = _init.reset & ~BGFX_RESET_INTERNAL_FORCE; + + setRenderContextSize(_init.swapChain); m_vendor = getGLString(GL_VENDOR); m_renderer = getGLString(GL_RENDERER); @@ -3202,6 +3204,12 @@ namespace bgfx { namespace gl FrameBufferGL& frameBuffer = m_frameBuffers[m_windows[ii].idx]; if (frameBuffer.m_needPresent) { + if (0 != frameBuffer.m_fbo[0]) + { + m_glctx.makeCurrent(frameBuffer.m_swapChain); + frameBuffer.blitSwapChainFbo(); + } + m_glctx.swap(frameBuffer.m_swapChain); frameBuffer.m_needPresent = false; } @@ -3659,11 +3667,6 @@ namespace bgfx { namespace gl release(mem); } - void overrideInternal(TextureHandle _handle, uintptr_t _ptr, uint16_t /*_layerIndex*/) override - { - m_textures[_handle.idx].overrideInternal(_ptr); - } - uintptr_t getInternal(TextureHandle _handle) override { return uintptr_t(m_textures[_handle.idx].m_id); @@ -3679,12 +3682,16 @@ namespace bgfx { namespace gl m_frameBuffers[_handle.idx].create(_num, _attachment); } - void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) override + void createFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override { - BX_UNUSED(_format, _depthFormat); uint16_t denseIdx = m_numWindows++; m_windows[denseIdx] = _handle; - m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height); + m_frameBuffers[_handle.idx].create(denseIdx, _desc); + } + + void resizeFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override + { + m_frameBuffers[_handle.idx].update(_desc); } void destroyFrameBuffer(FrameBufferHandle _handle) override @@ -3735,8 +3742,8 @@ namespace bgfx { namespace gl void requestScreenShot(FrameBufferHandle _handle, const char* _filePath) override { SwapChainGL* swapChain = NULL; - uint32_t width = m_resolution.width; - uint32_t height = m_resolution.height; + uint32_t width = m_mainSwapChain.width; + uint32_t height = m_mainSwapChain.height; if (isValid(_handle) ) { @@ -3745,6 +3752,12 @@ namespace bgfx { namespace gl width = frameBuffer.m_width; height = frameBuffer.m_height; } + else if (NULL == m_mainSwapChain.nwh + && NULL == g_platformData.context) + { + BX_TRACE("Unable to capture screenshot %s, no back buffer.", _filePath); + return; + } if (0 == width || 0 == height) @@ -3755,6 +3768,17 @@ namespace bgfx { namespace gl m_glctx.makeCurrent(swapChain); + if (isValid(_handle) + && NULL != m_frameBuffers[_handle.idx].m_swapChain + && 0 != m_frameBuffers[_handle.idx].m_fbo[0]) + { + FrameBufferGL& frameBuffer = m_frameBuffers[_handle.idx]; + + frameBuffer.resolveSwapChainFbo(); + + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBuffer.swapChainReadFbo() ) ); + } + uint32_t length = width*height*4; uint8_t* data = (uint8_t*)bx::alloc(g_allocator, length); @@ -3855,12 +3879,39 @@ namespace bgfx { namespace gl void submit(Frame* _render, const ClearQuad& _clearQuad, const MipGen& _mipGen, TextVideoMemBlitter& _textVideoMemBlitter) override; - void dbgTextRenderBegin(TextVideoMemBlitter& _blitter) override + void dbgTextRenderBegin(TextVideoMemBlitter& _blitter, FrameBufferHandle _handle) override { - uint32_t width = m_resolution.width; - uint32_t height = m_resolution.height; + uint32_t width; + uint32_t height; + + if (isValid(_handle) ) + { + FrameBufferGL& frameBuffer = m_frameBuffers[_handle.idx]; + width = frameBuffer.m_width; + height = frameBuffer.m_height; + + if (UINT16_MAX != frameBuffer.m_denseIdx) + { + m_glctx.makeCurrent(frameBuffer.m_swapChain); + frameBuffer.m_needPresent = true; + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + } + else + { + m_glctx.makeCurrent(NULL); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer.m_fbo[0]) ); + } + } + else + { + width = m_mainSwapChain.width; + height = m_mainSwapChain.height; + + m_glctx.makeCurrent(NULL); + m_needPresent = true; + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_backBufferFbo) ); + } - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_backBufferFbo) ); GL_CHECK(glViewport(0, 0, width, height) ); GL_CHECK(glDisable(GL_SCISSOR_TEST) ); @@ -3939,9 +3990,9 @@ namespace bgfx { namespace gl { } - void updateResolution(const Resolution& _resolution) + void updateResolution(const SwapChain& _swapChain, uint32_t _reset) { - float maxAnisotropy = !!(_resolution.reset & BGFX_RESET_MAXANISOTROPY) + float maxAnisotropy = !!(_reset & BGFX_RESET_MAXANISOTROPY) ? m_maxAnisotropyDefault : 0.0f ; @@ -3954,7 +4005,7 @@ namespace bgfx { namespace gl if (s_extension[Extension::ARB_depth_clamp].m_supported) { - if (!!(_resolution.reset & BGFX_RESET_DEPTH_CLAMP) ) + if (!!(_reset & BGFX_RESET_DEPTH_CLAMP) ) { GL_CHECK(glEnable(GL_DEPTH_CLAMP) ); } @@ -3970,19 +4021,21 @@ namespace bgfx { namespace gl | BGFX_RESET_SUSPEND ); - if (m_resolution.width != _resolution.width - || m_resolution.height != _resolution.height - || (m_resolution.reset&maskFlags) != (_resolution.reset&maskFlags) ) + if (m_mainSwapChain.width != _swapChain.width + || m_mainSwapChain.height != _swapChain.height + || m_mainSwapChain.nwh != _swapChain.nwh + || m_mainSwapChain.ndt != _swapChain.ndt + || (m_reset&maskFlags) != (_reset&maskFlags) ) { - uint32_t flags = _resolution.reset & (~BGFX_RESET_INTERNAL_FORCE); + uint32_t flags = _reset & (~BGFX_RESET_INTERNAL_FORCE); - m_resolution = _resolution; - m_resolution.reset = flags; + m_mainSwapChain = _swapChain; + m_reset = flags; - m_textVideoMem.resize(false, _resolution.width, _resolution.height); + m_textVideoMem.resize(false, _swapChain.width, _swapChain.height); m_textVideoMem.clear(); - setRenderContextSize(m_resolution); + setRenderContextSize(m_mainSwapChain); updateCapture(); for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) @@ -4059,7 +4112,7 @@ namespace bgfx { namespace gl GL_CHECK(glFrontFace(GL_CW) ); frameBuffer.m_needPresent = true; - m_currentFbo = 0; + m_currentFbo = frameBuffer.m_fbo[0]; } else { @@ -4079,7 +4132,12 @@ namespace bgfx { namespace gl { if (0 == m_currentFbo) { - if (0 != (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) ) + const uint32_t surfaceFlags = isValid(_fbh) + ? m_frameBuffers[_fbh.idx].m_desc.flags + : m_mainSwapChain.flags + ; + + if (0 != (surfaceFlags & BGFX_SWAP_CHAIN_SRGB_BACKBUFFER) ) { GL_CHECK(glEnable(GL_FRAMEBUFFER_SRGB) ); } @@ -4121,7 +4179,7 @@ namespace bgfx { namespace gl && 1 < _msaa && !m_glctx.m_msaaContext) { - GLenum storageFormat = m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER + GLenum storageFormat = m_mainSwapChain.flags & BGFX_SWAP_CHAIN_SRGB_BACKBUFFER ? GL_SRGB8_ALPHA8 : GL_RGBA8 ; @@ -4333,8 +4391,8 @@ namespace bgfx { namespace gl GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaBackBufferFbo) ); GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) ); - const uint32_t width = m_resolution.width; - const uint32_t height = m_resolution.height; + const uint32_t width = m_mainSwapChain.width; + const uint32_t height = m_mainSwapChain.height; const GLenum filter = BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) ? GL_NEAREST : GL_LINEAR @@ -4367,22 +4425,22 @@ namespace bgfx { namespace gl } } - void setRenderContextSize(const Resolution& _resolution) + void setRenderContextSize(const SwapChain& _swapChain) { if (!m_glctx.isValid() ) { - m_glctx.create(_resolution); + m_glctx.create(_swapChain, m_reset); } else { destroyMsaaFbo(); - m_glctx.resize(_resolution); + m_glctx.resize(_swapChain, m_reset); - uint32_t msaa = (_resolution.reset & BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + uint32_t msaa = (_swapChain.flags & BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT; msaa = bx::min(m_maxMsaa, msaa == 0 ? 0 : 1<captureBegin(m_resolution.width, m_resolution.height, m_resolution.width*4, TextureFormat::BGRA8, true); + g_callback->captureBegin(m_mainSwapChain.width, m_mainSwapChain.height, m_mainSwapChain.width*4, TextureFormat::BGRA8, true); } else { @@ -4529,8 +4587,8 @@ namespace bgfx { namespace gl { GL_CHECK(glReadPixels(0 , 0 - , m_resolution.width - , m_resolution.height + , m_mainSwapChain.width + , m_mainSwapChain.height , m_readPixelsFmt , GL_UNSIGNED_BYTE , m_capture @@ -4540,11 +4598,11 @@ namespace bgfx { namespace gl { bimg::imageSwizzleBgra8( m_capture - , m_resolution.width*4 - , m_resolution.width - , m_resolution.height + , m_mainSwapChain.width*4 + , m_mainSwapChain.width + , m_mainSwapChain.height , m_capture - , m_resolution.width*4 + , m_mainSwapChain.width*4 ); } @@ -5096,7 +5154,8 @@ namespace bgfx { namespace gl FrameBufferHandle m_fbh; uint16_t m_fbDiscard; - Resolution m_resolution; + SwapChain m_mainSwapChain; + uint32_t m_reset; void* m_capture; uint32_t m_captureSize; float m_maxAnisotropy; @@ -6396,13 +6455,6 @@ namespace bgfx { namespace gl } } - void TextureGL::overrideInternal(uintptr_t _ptr) - { - destroy(); - m_flags |= BGFX_SAMPLER_INTERNAL_SHARED; - m_id = (GLuint)_ptr; - } - void TextureGL::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) { const bimg::ImageBlockInfo& blockInfo = bimg::getBlockInfo(bimg::TextureFormat::Enum(m_requestedFormat) ); @@ -7177,6 +7229,11 @@ namespace bgfx { namespace gl void FrameBufferGL::postReset() { + if (NULL != m_swapChain) + { + return; + } + if (0 != m_fbo[0]) { GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[0]) ); @@ -7339,19 +7396,298 @@ namespace bgfx { namespace gl } } - void FrameBufferGL::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height) + void FrameBufferGL::create(uint16_t _denseIdx, const SwapChain& _desc) { - m_swapChain = s_renderGL->m_glctx.createSwapChain(_nwh, _width, _height); - m_width = _width; - m_height = _height; + m_swapChain = s_renderGL->m_glctx.createSwapChain( + _desc.nwh + , int32_t(_desc.width) + , int32_t(_desc.height) + ); + m_desc = _desc; + m_width = _desc.width; + m_height = _desc.height; m_numTh = 0; m_denseIdx = _denseIdx; m_needPresent = false; + + createSwapChainFbo(_desc); + } + + void FrameBufferGL::update(const SwapChain& _desc) + { + m_desc = _desc; + m_width = _desc.width; + m_height = _desc.height; + + destroySwapChainFbo(); + createSwapChainFbo(_desc); + } + + void FrameBufferGL::createSwapChainFbo(const SwapChain& _desc) + { + uint32_t msaa = (_desc.flags & BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT; + msaa = bx::min(s_renderGL->m_maxMsaa, 0 == msaa ? 1 : 1<m_glctx.makeCurrent(m_swapChain); + + GL_CHECK(glGenFramebuffers(1, &m_fbo[0]) ); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[0]) ); + + if (1 < msaa) + { + GL_CHECK(glGenRenderbuffers(1, &m_swapChainColorRbo) ); + GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_swapChainColorRbo) ); + GL_CHECK(glRenderbufferStorageMultisample( + GL_RENDERBUFFER + , msaa + , colorFormat + , _desc.width + , _desc.height + ) ); + GL_CHECK(glFramebufferRenderbuffer( + GL_FRAMEBUFFER + , GL_COLOR_ATTACHMENT0 + , GL_RENDERBUFFER + , m_swapChainColorRbo + ) ); + } + else + { + GL_CHECK(glGenTextures(1, &m_swapChainColorTex) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_swapChainColorTex) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) ); + GL_CHECK(glTexImage2D( + GL_TEXTURE_2D + , 0 + , colorFormat + , _desc.width + , _desc.height + , 0 + , GL_RGBA + , GL_UNSIGNED_BYTE + , NULL + ) ); + GL_CHECK(glFramebufferTexture2D( + GL_FRAMEBUFFER + , GL_COLOR_ATTACHMENT0 + , GL_TEXTURE_2D + , m_swapChainColorTex + , 0 + ) ); + } + + if (isValid(_desc.depth) ) + { + const TextureGL& depth = s_renderGL->m_textures[_desc.depth.idx]; + + GL_CHECK(glFramebufferTexture2D( + GL_FRAMEBUFFER + , attachmentFor(TextureFormat::Enum(depth.m_textureFormat) ) + , depth.m_target + , depth.m_id + , 0 + ) ); + } + else + { + GL_CHECK(glGenRenderbuffers(1, &m_swapChainDepthRbo) ); + GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_swapChainDepthRbo) ); + + if (1 < msaa) + { + GL_CHECK(glRenderbufferStorageMultisample( + GL_RENDERBUFFER + , msaa + , GL_DEPTH24_STENCIL8 + , _desc.width + , _desc.height + ) ); + } + else + { + GL_CHECK(glRenderbufferStorage( + GL_RENDERBUFFER + , GL_DEPTH24_STENCIL8 + , _desc.width + , _desc.height + ) ); + } + + GL_CHECK(glFramebufferRenderbuffer( + GL_FRAMEBUFFER + , GL_DEPTH_STENCIL_ATTACHMENT + , GL_RENDERBUFFER + , m_swapChainDepthRbo + ) ); + } + + BX_ASSERT(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER) + , "glCheckFramebufferStatus failed 0x%08x" + , glCheckFramebufferStatus(GL_FRAMEBUFFER) + ); + + if (1 < msaa) + { + GL_CHECK(glGenTextures(1, &m_swapChainColorTex) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_swapChainColorTex) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) ); + GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) ); + GL_CHECK(glTexImage2D( + GL_TEXTURE_2D + , 0 + , colorFormat + , _desc.width + , _desc.height + , 0 + , GL_RGBA + , GL_UNSIGNED_BYTE + , NULL + ) ); + + GL_CHECK(glGenFramebuffers(1, &m_fbo[1]) ); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[1]) ); + GL_CHECK(glFramebufferTexture2D( + GL_FRAMEBUFFER + , GL_COLOR_ATTACHMENT0 + , GL_TEXTURE_2D + , m_swapChainColorTex + , 0 + ) ); + + BX_ASSERT(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER) + , "glCheckFramebufferStatus failed 0x%08x" + , glCheckFramebufferStatus(GL_FRAMEBUFFER) + ); + } + + s_renderGL->m_glctx.makeCurrent(NULL); + } + + void FrameBufferGL::destroySwapChainFbo() + { + if (0 == m_fbo[0]) + { + return; + } + + s_renderGL->m_glctx.makeCurrent(m_swapChain); + + GL_CHECK(glDeleteFramebuffers(0 == m_fbo[1] ? 1 : 2, m_fbo) ); + + if (0 != m_swapChainColorTex) + { + GL_CHECK(glDeleteTextures(1, &m_swapChainColorTex) ); + } + + if (0 != m_swapChainColorRbo) + { + GL_CHECK(glDeleteRenderbuffers(1, &m_swapChainColorRbo) ); + } + + if (0 != m_swapChainDepthRbo) + { + GL_CHECK(glDeleteRenderbuffers(1, &m_swapChainDepthRbo) ); + } + + m_fbo[0] = 0; + m_fbo[1] = 0; + m_swapChainColorTex = 0; + m_swapChainColorRbo = 0; + m_swapChainDepthRbo = 0; + m_swapChainMsaa = 1; + + s_renderGL->m_glctx.makeCurrent(NULL); + } + + void FrameBufferGL::resolveSwapChainFbo() + { + if (0 == m_fbo[1]) + { + return; + } + + GL_CHECK(glDisable(GL_SCISSOR_TEST) ); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo[0]) ); + GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo[1]) ); + GL_CHECK(glBlitFramebuffer( + 0 + , 0 + , m_width + , m_height + , 0 + , 0 + , m_width + , m_height + , GL_COLOR_BUFFER_BIT + , GL_NEAREST + ) ); + + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[0]) ); + } + + void FrameBufferGL::blitSwapChainFbo() + { + if (0 == m_fbo[0]) + { + return; + } + + GL_CHECK(glDisable(GL_SCISSOR_TEST) ); + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo[0]) ); + GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) ); + + if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES) ) + { + GL_CHECK(glUseProgram(s_renderGL->m_msaaBlitProgram) ); + GL_CHECK(glActiveTexture(GL_TEXTURE0) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_swapChainColorTex) ); + GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, 3) ); + } + else + { + GL_CHECK(glBlitFramebuffer( + 0 + , 0 + , m_width + , m_height + , 0 + , 0 + , m_width + , m_height + , GL_COLOR_BUFFER_BIT + , GL_NEAREST + ) ); + } + + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); } uint16_t FrameBufferGL::destroy() { - if (0 != m_fbo[0]) + if (NULL != m_swapChain) + { + destroySwapChainFbo(); + } + else if (0 != m_fbo[0]) { GL_CHECK(glDeleteFramebuffers(0 == m_fbo[1] ? 1 : 2, m_fbo) ); m_num = 0; @@ -8136,7 +8472,7 @@ namespace bgfx { namespace gl GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_backBufferFbo) ); GL_CHECK(glFrontFace(GL_CW) ); - updateResolution(_render->m_resolution); + updateResolution(_render->m_mainSwapChain, _render->m_reset); int64_t timeBegin = bx::getHPCounter(); int64_t captureElapsed = 0; @@ -8184,7 +8520,7 @@ namespace bgfx { namespace gl UniformCacheState ucs(_render); BlitState bs(_render); - int32_t resolutionHeight = _render->m_resolution.height; + int32_t resolutionHeight = _render->m_mainSwapChain.height; uint32_t blendFactor = 0; uint8_t primIndex; @@ -8280,7 +8616,7 @@ namespace bgfx { namespace gl if (_render->m_view[view].m_fbh.idx != fbh.idx) { fbh = _render->m_view[view].m_fbh; - resolutionHeight = _render->m_resolution.height; + resolutionHeight = _render->m_mainSwapChain.height; resolutionHeight = setFrameBuffer(fbh, resolutionHeight, discardFlags); } @@ -9319,7 +9655,7 @@ namespace bgfx { namespace gl if (0 < _render->m_numRenderItems) { - if (0 != (m_resolution.reset & BGFX_RESET_FLUSH_AFTER_RENDER) ) + if (0 != (m_reset & BGFX_RESET_FLUSH_AFTER_RENDER) ) { GL_CHECK(glFlush() ); } @@ -9430,12 +9766,12 @@ namespace bgfx { namespace gl , freq/frameTime ); - const uint32_t msaa = (m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + const uint32_t msaa = (m_mainSwapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT; tvm.printf(10, pos++, 0x8b, " Reset flags: [%c] vsync, [%c] MSAAx%d, [%c] MaxAnisotropy " - , !!(m_resolution.reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' + , !!(m_reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' , 0 != msaa ? '\xfe' : ' ' , 1<m_debugFrameBuffer, _render->m_debugTextScale); BGFX_GL_PROFILER_END(); } @@ -9571,7 +9907,7 @@ namespace bgfx { namespace gl { BGFX_GL_PROFILER_BEGIN_LITERAL("debugtext", kColorFrame); - dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem); + dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem, _render->m_debugFrameBuffer, _render->m_debugTextScale); BGFX_GL_PROFILER_END(); } diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 5b5361191..02380e4d5 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -1471,7 +1471,6 @@ namespace bgfx { namespace gl bool init(GLenum _target, uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips, uint64_t _flags, uint64_t _external = 0); void create(const Memory* _mem, uint64_t _flags, uint8_t _skip, uint64_t _external = 0); void destroy(); - void overrideInternal(uintptr_t _ptr); void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void clear(uint8_t _mip, uint8_t _numMips, uint16_t _layer, uint16_t _numLayers); void setSamplerState(uint32_t _flags, const float _rgba[4]); @@ -1547,6 +1546,10 @@ namespace bgfx { namespace gl { FrameBufferGL() : m_swapChain(NULL) + , m_swapChainColorTex(0) + , m_swapChainColorRbo(0) + , m_swapChainDepthRbo(0) + , m_swapChainMsaa(1) , m_denseIdx(UINT16_MAX) , m_num(0) , m_needPresent(false) @@ -1555,13 +1558,29 @@ namespace bgfx { namespace gl } void create(uint8_t _num, const Attachment* _attachment); - void create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height); + void create(uint16_t _denseIdx, const SwapChain& _desc); + void update(const SwapChain& _desc); void postReset(); uint16_t destroy(); void resolve(); void discard(uint16_t _flags); + void createSwapChainFbo(const SwapChain& _desc); + void destroySwapChainFbo(); + void resolveSwapChainFbo(); + void blitSwapChainFbo(); + + GLuint swapChainReadFbo() const + { + return 0 != m_fbo[1] ? m_fbo[1] : m_fbo[0]; + } + SwapChainGL* m_swapChain; + SwapChain m_desc; + GLuint m_swapChainColorTex; + GLuint m_swapChainColorRbo; + GLuint m_swapChainDepthRbo; + uint32_t m_swapChainMsaa; GLuint m_fbo[2]; uint32_t m_width; uint32_t m_height; diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp index 6dc42be01..177d97b04 100644 --- a/src/renderer_mtl.cpp +++ b/src/renderer_mtl.cpp @@ -910,7 +910,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_fbh = BGFX_INVALID_HANDLE; bx::memSet(m_uniforms, 0, sizeof(m_uniforms) ); - m_resolution = _init.resolution; + m_mainSwapChain = _init.swapChain; m_device = (MTL::Device*)g_platformData.context; @@ -1172,24 +1172,18 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_vertexDescriptor = newVertexDescriptor(); m_samplerDescriptor = newSamplerDescriptor(); - if (NULL == g_platformData.nwh) + if (NULL == _init.swapChain.nwh) { BX_TRACE("Headless."); } else { - m_mainFrameBuffer.create( - 0 - , g_platformData.nwh - , m_resolution.width - , m_resolution.height - , m_resolution.formatColor - , m_resolution.formatDepthStencil - ); - m_textVideoMem.resize(false, m_resolution.width, m_resolution.height); + m_mainFrameBuffer.create(0, m_mainSwapChain); + m_textVideoMem.resize(false, m_mainSwapChain.width, m_mainSwapChain.height); m_textVideoMem.clear(); m_numWindows = 1; + m_windows[0] = BGFX_INVALID_HANDLE; if (NULL == m_mainFrameBuffer.m_swapChain->m_metalLayer) { @@ -1198,7 +1192,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames } } - m_cmd.init(m_device, _init.resolution.maxFrameLatency); + m_cmd.init(m_device, _init.swapChain.maxFrameLatency); BGFX_FATAL(NULL != m_cmd.m_commandQueue, Fatal::UnableToInitialize, "Unable to create Metal device."); m_uniformScratchBuffer.createUniform(2<<20, BGFX_CONFIG_MAX_FRAME_LATENCY); @@ -1737,11 +1731,6 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames release(mem); } - void overrideInternal(TextureHandle _handle, uintptr_t _ptr, uint16_t /*_layerIndex*/) override - { - m_textures[_handle.idx].overrideInternal(_ptr); - } - uintptr_t getInternal(TextureHandle _handle) override { return uintptr_t(m_textures[_handle.idx].m_ptr); @@ -1757,13 +1746,13 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_frameBuffers[_handle.idx].create(_num, _attachment); } - void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) override + void createFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override { for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) { FrameBufferHandle handle = m_windows[ii]; if (isValid(handle) - && m_frameBuffers[handle.idx].m_nwh == _nwh) + && m_frameBuffers[handle.idx].m_nwh == _desc.nwh) { destroyFrameBuffer(handle); } @@ -1773,7 +1762,16 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_windows[denseIdx] = _handle; FrameBufferMtl& fb = m_frameBuffers[_handle.idx]; - fb.create(denseIdx, _nwh, _width, _height, _format, _depthFormat); + fb.create(denseIdx, _desc); + } + + void resizeFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override + { + FrameBufferMtl& fb = m_frameBuffers[_handle.idx]; + + fb.m_width = _desc.width; + fb.m_height = _desc.height; + fb.resizeSwapChain(_desc); } void destroyFrameBuffer(FrameBufferHandle _handle) override @@ -1824,12 +1822,25 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_uniformReg.remove(_handle); } + FrameBufferMtl& getFrameBuffer(FrameBufferHandle _fbh) + { + return isValid(_fbh) + ? m_frameBuffers[_fbh.idx] + : m_mainFrameBuffer + ; + } + + const FrameBufferMtl& getFrameBuffer(FrameBufferHandle _fbh) const + { + return isValid(_fbh) + ? m_frameBuffers[_fbh.idx] + : m_mainFrameBuffer + ; + } + void requestScreenShot(FrameBufferHandle _handle, const char* _filePath) override { - SwapChainMtl* swapChain = isValid(_handle) - ? m_frameBuffers[_handle.idx].m_swapChain - : m_mainFrameBuffer.m_swapChain - ; + SwapChainMtl* swapChain = getFrameBuffer(_handle).m_swapChain; if (NULL == swapChain || NULL == swapChain->m_screenshotTarget) @@ -1936,8 +1947,9 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames void submit(Frame* _render, const ClearQuad& _clearQuad, const MipGen& _mipGen, TextVideoMemBlitter& _textVideoMemBlitter) override; - void dbgTextRenderBegin(TextVideoMemBlitter& /*_blitter*/) override + void dbgTextRenderBegin(TextVideoMemBlitter& /*_blitter*/, FrameBufferHandle _handle) override { + m_dbgTextFbh = _handle; } void dbgTextRender(TextVideoMemBlitter& _blitter, uint32_t _numIndices) override @@ -1960,10 +1972,11 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames endEncoding(); - const uint32_t width = m_resolution.width; - const uint32_t height = m_resolution.height; + const FrameBufferHandle fbh = m_dbgTextFbh; + const FrameBufferMtl& frameBuffer = getFrameBuffer(fbh); - FrameBufferHandle fbh = BGFX_INVALID_HANDLE; + const uint32_t width = frameBuffer.m_width; + const uint32_t height = frameBuffer.m_height; MTL::RenderPassDescriptor* renderPassDescriptor = newRenderPassDescriptor(); @@ -2067,7 +2080,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames bool needPresent = false; for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) { - FrameBufferMtl& frameBuffer = ii == 0 ? m_mainFrameBuffer : m_frameBuffers[m_windows[ii].idx]; + FrameBufferMtl& frameBuffer = getFrameBuffer(m_windows[ii]); if (NULL != frameBuffer.m_swapChain && frameBuffer.m_swapChain->m_drawableTexture) { @@ -2085,7 +2098,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) { - FrameBufferMtl& frameBuffer = ii == 0 ? m_mainFrameBuffer : m_frameBuffers[m_windows[ii].idx]; + FrameBufferMtl& frameBuffer = getFrameBuffer(m_windows[ii]); if (NULL != frameBuffer.m_swapChain && frameBuffer.m_swapChain->m_drawableTexture) @@ -2103,20 +2116,20 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_cmd.kick(false, false); } - void updateResolution(const Resolution& _resolution) + void updateResolution(const SwapChain& _swapChain, uint32_t _reset) { SwapChainMtl* swapChain = m_mainFrameBuffer.m_swapChain; if (NULL != swapChain) { - swapChain->m_maxAnisotropy = !!(_resolution.reset & BGFX_RESET_MAXANISOTROPY) + swapChain->m_maxAnisotropy = !!(_reset & BGFX_RESET_MAXANISOTROPY) ? 16 : 1 ; } m_depthClamp = m_supportsDepthClipMode - && !!(_resolution.reset & BGFX_RESET_DEPTH_CLAMP); + && !!(_reset & BGFX_RESET_DEPTH_CLAMP); uint32_t maskFlags = ~(0 | BGFX_RESET_MAXANISOTROPY @@ -2127,21 +2140,18 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames #if BX_PLATFORM_OSX # if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 if (m_hasVSync - && !!((_resolution.reset ^ m_resolution.reset) & BGFX_RESET_VSYNC) ) + && !!((_reset ^ m_reset) & BGFX_RESET_VSYNC) ) { - m_resolution.reset = 0 - | (m_resolution.reset & ~BGFX_RESET_VSYNC) - | ( _resolution.reset & BGFX_RESET_VSYNC) + m_reset = 0 + | (m_reset & ~BGFX_RESET_VSYNC) + | ( _reset & BGFX_RESET_VSYNC) ; - const bool displaySync = !!(m_resolution.reset & BGFX_RESET_VSYNC); + const bool displaySync = !!(m_reset & BGFX_RESET_VSYNC); for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) { - FrameBufferMtl& fb = 0 == ii - ? m_mainFrameBuffer - : m_frameBuffers[m_windows[ii].idx] - ; + FrameBufferMtl& fb = getFrameBuffer(m_windows[ii]); if (NULL != fb.m_swapChain && NULL != fb.m_swapChain->m_metalLayer) @@ -2155,26 +2165,28 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames # endif // __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 #endif // BX_PLATFORM_OSX - if (m_resolution.width != _resolution.width - || m_resolution.height != _resolution.height - || (m_resolution.reset&maskFlags) != (_resolution.reset&maskFlags) ) + if (m_mainSwapChain.width != _swapChain.width + || m_mainSwapChain.height != _swapChain.height + || m_mainSwapChain.nwh != _swapChain.nwh + || m_mainSwapChain.ndt != _swapChain.ndt + || (m_reset&maskFlags) != (_reset&maskFlags) ) { - m_resolution = _resolution; + m_mainSwapChain = _swapChain; const MTL::PixelFormat prevPixelFormat = getSwapChainPixelFormat(swapChain); if (NULL != swapChain) { - if (m_resolution.reset & BGFX_RESET_INTERNAL_FORCE - && swapChain->m_nwh != g_platformData.nwh) + if (m_reset & BGFX_RESET_INTERNAL_FORCE + && swapChain->m_nwh != m_mainSwapChain.nwh) { - swapChain->init(g_platformData.nwh); + swapChain->init(m_mainSwapChain.nwh); } - m_mainFrameBuffer.resizeSwapChain(_resolution.width, _resolution.height); + m_mainFrameBuffer.resizeSwapChain(_swapChain); } - m_resolution.reset &= ~BGFX_RESET_INTERNAL_FORCE; + m_reset &= ~BGFX_RESET_INTERNAL_FORCE; for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) { @@ -2183,7 +2195,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames updateCapture(); - m_textVideoMem.resize(false, _resolution.width, _resolution.height); + m_textVideoMem.resize(false, _swapChain.width, _swapChain.height); m_textVideoMem.clear(); const MTL::PixelFormat pixelFormat = getSwapChainPixelFormat(swapChain); @@ -2212,11 +2224,11 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames void updateCapture() { - if (m_resolution.reset&BGFX_RESET_CAPTURE) + if (m_reset&BGFX_RESET_CAPTURE) { - m_captureSize = m_resolution.width*m_resolution.height*4; + m_captureSize = m_mainSwapChain.width*m_mainSwapChain.height*4; m_capture = bx::realloc(g_allocator, m_capture, m_captureSize); - g_callback->captureBegin(m_resolution.width, m_resolution.height, m_resolution.width*4, TextureFormat::BGRA8, false); + g_callback->captureBegin(m_mainSwapChain.width, m_mainSwapChain.height, m_mainSwapChain.width*4, TextureFormat::BGRA8, false); } else { @@ -2241,10 +2253,10 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_cmd.kick(false, true); m_commandBuffer = 0; - MTL::Region region(0, 0, 0, m_resolution.width, m_resolution.height, 1); + MTL::Region region(0, 0, 0, m_mainSwapChain.width, m_mainSwapChain.height, 1); - const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_resolution.formatColor) ); - const uint32_t pitch = m_resolution.width * bpp / 8; + const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_mainSwapChain.formatColor) ); + const uint32_t pitch = m_mainSwapChain.width * bpp / 8; swapChain->m_screenshotTarget->getBytes(m_capture, pitch, 0, region, 0, 0); @@ -2562,10 +2574,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (!isValid(_fbh) || m_frameBuffers[_fbh.idx].m_swapChain) { - SwapChainMtl* swapChain = !isValid(_fbh) - ? m_mainFrameBuffer.m_swapChain - : m_frameBuffers[_fbh.idx].m_swapChain - ; + SwapChainMtl* swapChain = getFrameBuffer(_fbh).m_swapChain; if (NULL != swapChain) { @@ -2592,8 +2601,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames } else { - _renderPassDescriptor->setRenderTargetWidth( bx::max(1, m_resolution.width) ); - _renderPassDescriptor->setRenderTargetHeight(bx::max(1, m_resolution.height) ); + _renderPassDescriptor->setRenderTargetWidth( bx::max(1, m_mainSwapChain.width) ); + _renderPassDescriptor->setRenderTargetHeight(bx::max(1, m_mainSwapChain.height) ); _renderPassDescriptor->setDefaultRasterSampleCount(1); } } @@ -3093,10 +3102,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames if (!isValid(_fbh) || s_renderMtl->m_frameBuffers[_fbh.idx].m_swapChain) { - SwapChainMtl* swapChain = !isValid(_fbh) - ? s_renderMtl->m_mainFrameBuffer.m_swapChain - : s_renderMtl->m_frameBuffers[_fbh.idx].m_swapChain - ; + SwapChainMtl* swapChain = s_renderMtl->getFrameBuffer(_fbh).m_swapChain; if (NULL != swapChain) { @@ -3720,7 +3726,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames FrameBufferHandle m_fbh; bool m_rtMsaa; - Resolution m_resolution; + SwapChain m_mainSwapChain; + uint32_t m_reset; void* m_capture; uint32_t m_captureSize; @@ -3748,6 +3755,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames MTL::RenderCommandEncoder* m_renderCommandEncoder; MTL::ComputeCommandEncoder* m_computeCommandEncoder; FrameBufferHandle m_renderCommandEncoderFbh; + FrameBufferHandle m_dbgTextFbh; }; PipelineStateMtl* videoGetComputePipelineState(RendererContextMtl* _renderer, ProgramHandle _handle) @@ -4449,13 +4457,6 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_ptrViews.clear(); } - void TextureMtl::overrideInternal(uintptr_t _ptr) - { - destroy(); - m_flags |= BGFX_SAMPLER_INTERNAL_SHARED; - m_ptr = (MTL::Texture*)(void*)_ptr; - } - void TextureMtl::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) { if (0 != (m_flags & BGFX_TEXTURE_INTERNAL_VIDEO_DECODE_DST) ) @@ -4917,12 +4918,6 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_metalLayer->setDevice(s_renderMtl->m_device); MtlObjAccess::send(m_metalLayer, sel_registerName("setMagnificationFilter:"), nsstr("nearest") ); - const Resolution& resolution = s_renderMtl->m_resolution; - m_metalLayer->setPixelFormat( (MTL::PixelFormat)( (resolution.reset & BGFX_RESET_SRGB_BACKBUFFER) - ? s_textureFormat[resolution.formatColor].fmtSrgb - : s_textureFormat[resolution.formatColor].fmt) ) - ; - retain(m_metalLayer); } @@ -4931,37 +4926,38 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames void SwapChainMtl::releaseBackBuffer() { - MTL_RELEASE(m_backBufferStencil, m_backBufferDepth == m_backBufferStencil ? 1 : 0); - MTL_RELEASE_W(m_backBufferDepth, 0); + if (m_borrowedDepth) + { + m_backBufferDepth = NULL; + m_backBufferStencil = NULL; + m_borrowedDepth = false; + } + else + { + MTL_RELEASE(m_backBufferStencil, m_backBufferDepth == m_backBufferStencil ? 1 : 0); + MTL_RELEASE_W(m_backBufferDepth, 0); + } + MTL_RELEASE_W(m_backBufferColorMsaa, 0); } - uint32_t SwapChainMtl::resize(uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) + uint32_t SwapChainMtl::resize(const SwapChain& _desc) { releaseBackBuffer(); - const Resolution& resolution = s_renderMtl->m_resolution; - - const uint32_t resetFlags = resolution.reset; - const uint32_t maxFrameLatency = resolution.maxFrameLatency; - const TextureFormat::Enum formatColor = TextureFormat::Count == _format - ? resolution.formatColor - : _format - ; - const TextureFormat::Enum formatDepthStencil = TextureFormat::Count == _depthFormat - ? resolution.formatDepthStencil - : _depthFormat - ; + const uint32_t maxFrameLatency = _desc.maxFrameLatency; + const TextureFormat::Enum formatColor = _desc.formatColor; + const TextureFormat::Enum formatDepthStencil = _desc.formatDepthStencil; m_colorFormat = formatColor; - const int32_t sampleCount = s_msaa[(resetFlags & BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; + const int32_t sampleCount = s_msaa[(_desc.flags & BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT]; #if BX_PLATFORM_OSX # if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 if (s_renderMtl->m_hasVSync) { - m_metalLayer->setDisplaySyncEnabled(!!(resetFlags & BGFX_RESET_VSYNC) ); + m_metalLayer->setDisplaySyncEnabled(!!(s_renderMtl->m_reset & BGFX_RESET_VSYNC) ); } if (s_renderMtl->m_hasMaximumDrawableCount) @@ -4976,16 +4972,16 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames #endif // BX_PLATFORM_OSX { - m_metalLayer->setDrawableSize(CGSizeMake(_width, _height) ); - m_metalLayer->setPixelFormat( (MTL::PixelFormat)( (resetFlags & BGFX_RESET_SRGB_BACKBUFFER) + m_metalLayer->setDrawableSize(CGSizeMake(_desc.width, _desc.height) ); + m_metalLayer->setPixelFormat( (MTL::PixelFormat)( (_desc.flags & BGFX_SWAP_CHAIN_SRGB_BACKBUFFER) ? s_textureFormat[formatColor].fmtSrgb : s_textureFormat[formatColor].fmt) ) ; const CGSize actualSize = m_metalLayer->drawableSize(); BX_WARN(true - && uint32_t(actualSize.width) == _width - && uint32_t(actualSize.height) == _height + && uint32_t(actualSize.width) == _desc.width + && uint32_t(actualSize.height) == _desc.height , "CAMetalLayer drawableSize is %ux%u after requesting %ux%u. " "The host layer (MTKView? with autoReizeDrawable=YES) " "is overriding the size requested via bgfx::init/reset. " @@ -4993,8 +4989,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames "drawable size to bgfx." , uint32_t(actualSize.width) , uint32_t(actualSize.height) - , _width - , _height + , _desc.width + , _desc.height ); BX_UNUSED(actualSize); } @@ -5006,8 +5002,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames : MTL::TextureType2D) ; - desc->setWidth(_width); - desc->setHeight(_height); + desc->setWidth(_desc.width); + desc->setHeight(_desc.height); desc->setDepth(1); desc->setMipmapLevelCount(1); desc->setSampleCount(sampleCount); @@ -5022,7 +5018,18 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames desc->setUsage(MTL::TextureUsageRenderTarget); } - if (bimg::isDepth(bimg::TextureFormat::Enum(formatDepthStencil) ) ) + if (isValid(_desc.depth) ) + { + const TextureMtl& depth = s_renderMtl->m_textures[_desc.depth.idx]; + + m_backBufferDepth = depth.m_ptr; + m_backBufferStencil = NULL != depth.m_ptrStencil + ? depth.m_ptrStencil + : depth.m_ptr + ; + m_borrowedDepth = true; + } + else if (bimg::isDepth(bimg::TextureFormat::Enum(formatDepthStencil) ) ) { const MTL::PixelFormat depthFormat = s_textureFormat[formatDepthStencil].fmt; @@ -5188,18 +5195,17 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_pixelFormatHash = murmur.end(); } - void FrameBufferMtl::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) + void FrameBufferMtl::create(uint16_t _denseIdx, const SwapChain& _desc) { - BX_UNUSED(_format, _depthFormat); m_swapChain = BX_NEW(g_allocator, SwapChainMtl); m_num = 0; - m_width = _width; - m_height = _height; - m_nwh = _nwh; + m_width = _desc.width; + m_height = _desc.height; + m_nwh = _desc.nwh; m_denseIdx = _denseIdx; - m_swapChain->init(_nwh); - resizeSwapChain(_width, _height, _format, _depthFormat); + m_swapChain->init(_desc.nwh); + resizeSwapChain(_desc); } void FrameBufferMtl::postReset() @@ -5280,9 +5286,9 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames s_renderMtl->endEncoding(); } - void FrameBufferMtl::resizeSwapChain(uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) + void FrameBufferMtl::resizeSwapChain(const SwapChain& _desc) { - m_pixelFormatHash = m_swapChain->resize(_width, _height, _format, _depthFormat); + m_pixelFormatHash = m_swapChain->resize(_desc); } void CommandQueueMtl::init(MTL::Device* _device, uint32_t _maxFrameLatency) @@ -5929,14 +5935,11 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames m_blitCommandEncoder = NULL; } - updateResolution(_render->m_resolution); + updateResolution(_render->m_mainSwapChain, _render->m_reset); for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) { - FrameBufferMtl& frameBuffer = 0 == ii - ? m_mainFrameBuffer - : m_frameBuffers[m_windows[ii].idx] - ; + FrameBufferMtl& frameBuffer = getFrameBuffer(m_windows[ii]); SwapChainMtl* swapChain = frameBuffer.m_swapChain; @@ -5954,8 +5957,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames needScreenshot = _render->m_screenShot[jj].handle.idx == fbhIdx; } - const uint32_t width = 0 == ii ? m_resolution.width : frameBuffer.m_width; - const uint32_t height = 0 == ii ? m_resolution.height : frameBuffer.m_height; + const uint32_t width = 0 == ii ? m_mainSwapChain.width : frameBuffer.m_width; + const uint32_t height = 0 == ii ? m_mainSwapChain.height : frameBuffer.m_height; if (needScreenshot) { @@ -6133,8 +6136,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames { const FrameBufferHandle viewFbh = _render->m_view[view].m_fbh; - uint32_t width = m_resolution.width; - uint32_t height = m_resolution.height; + uint32_t width = m_mainSwapChain.width; + uint32_t height = m_mainSwapChain.height; if (isValid(viewFbh) ) { @@ -7139,12 +7142,12 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames , freq/frameTime ); - const uint32_t msaa = (m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + const uint32_t msaa = (m_mainSwapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT; tvm.printf(10, pos++, 0x8b, " Reset flags: [%c] vsync, [%c] MSAAx%d, [%c] MaxAnisotropy " - , !!(m_resolution.reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' + , !!(m_reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' , 0 != msaa ? '\xfe' : ' ' , 1<m_debugFrameBuffer, _render->m_debugTextScale); rce = m_renderCommandEncoder; rce->popDebugGroup(); @@ -7199,7 +7202,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames { rce->pushDebugGroup(nsstr("debugtext") ); - dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem); + dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem, _render->m_debugFrameBuffer, _render->m_debugTextScale); rce = m_renderCommandEncoder; rce->popDebugGroup(); @@ -7220,10 +7223,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) { - FrameBufferMtl& frameBuffer = 0 == ii - ? m_mainFrameBuffer - : m_frameBuffers[m_windows[ii].idx] - ; + FrameBufferMtl& frameBuffer = getFrameBuffer(m_windows[ii]); SwapChainMtl* swapChain = frameBuffer.m_swapChain; diff --git a/src/renderer_mtl.h b/src/renderer_mtl.h index 41106b1df..cb2c7bd46 100644 --- a/src/renderer_mtl.h +++ b/src/renderer_mtl.h @@ -432,8 +432,6 @@ namespace bgfx { namespace mtl void create(const Memory* _mem, uint64_t _flags, uint8_t _skip, uint64_t _external); void destroy(); - void overrideInternal(uintptr_t _ptr); - void update( uint8_t _side , uint8_t _mip @@ -491,6 +489,7 @@ namespace bgfx { namespace mtl , m_backBufferStencil() , m_maxAnisotropy(0) , m_colorFormat(TextureFormat::Count) + , m_borrowedDepth(false) { } @@ -500,7 +499,7 @@ namespace bgfx { namespace mtl void releaseBackBuffer(); - uint32_t resize(uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat); + uint32_t resize(const SwapChain& _desc); MTL::Texture* currentDrawableTexture(); @@ -517,6 +516,7 @@ namespace bgfx { namespace mtl uint32_t m_maxAnisotropy; void* m_nwh; TextureFormat::Enum m_colorFormat; + bool m_borrowedDepth; }; struct FrameBufferMtl @@ -532,24 +532,12 @@ namespace bgfx { namespace mtl } void create(uint8_t _num, const Attachment* _attachment); - void create( - uint16_t _denseIdx - , void* _nwh - , uint32_t _width - , uint32_t _height - , TextureFormat::Enum _format - , TextureFormat::Enum _depthFormat - ); + void create(uint16_t _denseIdx, const SwapChain& _desc); void postReset(); uint16_t destroy(); void resolve(); - void resizeSwapChain( - uint32_t _width - , uint32_t _height - , TextureFormat::Enum _format = TextureFormat::Count - , TextureFormat::Enum _depthFormat = TextureFormat::Count - ); + void resizeSwapChain(const SwapChain& _desc); SwapChainMtl* m_swapChain; void* m_nwh; diff --git a/src/renderer_noop.cpp b/src/renderer_noop.cpp index 2baa2d8e7..12e260a19 100644 --- a/src/renderer_noop.cpp +++ b/src/renderer_noop.cpp @@ -190,10 +190,6 @@ namespace bgfx { namespace noop { } - void overrideInternal(TextureHandle /*_handle*/, uintptr_t /*_ptr*/, uint16_t /*_layerIndex*/) override - { - } - uintptr_t getInternal(TextureHandle /*_handle*/) override { return 0; @@ -207,7 +203,7 @@ namespace bgfx { namespace noop { } - void createFrameBuffer(FrameBufferHandle /*_handle*/, void* /*_nwh*/, uint32_t /*_width*/, uint32_t /*_height*/, TextureFormat::Enum /*_format*/, TextureFormat::Enum /*_depthFormat*/) override + void createFrameBuffer(FrameBufferHandle /*_handle*/, const SwapChain& /*_desc*/) override { } @@ -268,7 +264,7 @@ namespace bgfx { namespace noop perfStats.gpuMemoryUsed = -INT64_MAX; } - void dbgTextRenderBegin(TextVideoMemBlitter& /*_blitter*/) override + void dbgTextRenderBegin(TextVideoMemBlitter& /*_blitter*/, FrameBufferHandle /*_handle*/) override { } diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index f8e0f756f..2659898fa 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -1269,7 +1269,7 @@ VK_IMPORT_DEVICE ErrorState::Enum errorState = ErrorState::Default; - const bool headless = NULL == g_platformData.nwh; + const bool headless = NULL == _init.swapChain.nwh; const void* nextFeatures = NULL; @@ -1280,7 +1280,7 @@ VK_IMPORT_DEVICE m_fbh = BGFX_INVALID_HANDLE; bx::memSet(m_uniforms, 0, sizeof(m_uniforms) ); - bx::memSet(&m_resolution, 0, sizeof(m_resolution) ); + bx::memSet(&m_mainSwapChain, 0, sizeof(m_mainSwapChain) ); bool imported = true; VkResult result; @@ -2207,9 +2207,9 @@ VK_IMPORT_DEVICE } { - m_maxFrameLatency = _init.resolution.maxFrameLatency == 0 + m_maxFrameLatency = _init.swapChain.maxFrameLatency == 0 ? BGFX_CONFIG_MAX_FRAME_LATENCY - : _init.resolution.maxFrameLatency + : _init.swapChain.maxFrameLatency ; result = m_cmd.init(m_globalQueueFamily, m_globalQueue); @@ -2234,23 +2234,17 @@ VK_IMPORT_DEVICE m_presentElapsed = 0; { - m_resolution = _init.resolution; - m_resolution.reset &= ~BGFX_RESET_INTERNAL_FORCE; + m_mainSwapChain = _init.swapChain; + m_reset &= ~BGFX_RESET_INTERNAL_FORCE; m_numWindows = 0; if (!headless) { - m_textVideoMem.resize(false, _init.resolution.width, _init.resolution.height); + m_textVideoMem.resize(false, _init.swapChain.width, _init.swapChain.height); m_textVideoMem.clear(); - result = m_backBuffer.create( - UINT16_MAX - , g_platformData.nwh - , m_resolution.width - , m_resolution.height - , m_resolution.formatColor - ); + result = m_backBuffer.create(UINT16_MAX, m_mainSwapChain); if (VK_SUCCESS != result) { @@ -2599,12 +2593,7 @@ VK_IMPORT_DEVICE for (uint16_t ii = 0; ii < m_numWindows; ++ii) { - FrameBufferVK& fb = isValid(m_windows[ii]) - ? m_frameBuffers[m_windows[ii].idx] - : m_backBuffer - ; - - fb.present(); + getFrameBuffer(m_windows[ii]).present(); } const int64_t now = bx::getHPCounter(); @@ -2807,10 +2796,6 @@ VK_IMPORT_DEVICE bgfx::release(mem); } - void overrideInternal(TextureHandle /*_handle*/, uintptr_t /*_ptr*/, uint16_t /*_layerIndex*/) override - { - } - uintptr_t getInternal(TextureHandle /*_handle*/) override { return 0; @@ -2827,13 +2812,13 @@ VK_IMPORT_DEVICE m_frameBuffers[_handle.idx].create(_num, _attachment); } - void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) override + void createFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override { for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) { FrameBufferHandle handle = m_windows[ii]; if (isValid(handle) - && m_frameBuffers[handle.idx].m_nwh == _nwh) + && m_frameBuffers[handle.idx].m_nwh == _desc.nwh) { destroyFrameBuffer(handle); } @@ -2841,13 +2826,17 @@ VK_IMPORT_DEVICE uint16_t denseIdx = m_numWindows++; m_windows[denseIdx] = _handle; - VK_CHECK(m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _format, _depthFormat) ); + VK_CHECK(m_frameBuffers[_handle.idx].create(denseIdx, _desc) ); + } + + void resizeFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override + { + m_frameBuffers[_handle.idx].update(m_commandBuffer, _desc); } void destroyFrameBuffer(FrameBufferHandle _handle) override { FrameBufferVK& frameBuffer = m_frameBuffers[_handle.idx]; - if (m_fbh.idx == _handle.idx) { m_fbh = BGFX_INVALID_HANDLE; @@ -2892,10 +2881,7 @@ VK_IMPORT_DEVICE void requestScreenShot(FrameBufferHandle _fbh, const char* _filePath) override { - const FrameBufferVK& frameBuffer = isValid(_fbh) - ? m_frameBuffers[_fbh.idx] - : m_backBuffer - ; + FrameBufferVK& frameBuffer = getFrameBuffer(_fbh); const SwapChainVK& swapChain = frameBuffer.m_swapChain; if (!isSwapChainReadable(swapChain) ) @@ -2904,6 +2890,8 @@ VK_IMPORT_DEVICE return; } + frameBuffer.resolve(); + auto callback = [](void* _src, uint32_t _width, uint32_t _height, bgfx::TextureFormat::Enum _format, uint32_t _pitch, const void* _userData) { const char* filePath = (const char*)_userData; @@ -3024,12 +3012,15 @@ VK_IMPORT_DEVICE void submit(Frame* _render, const ClearQuad& _clearQuad, const MipGen& _mipGen, TextVideoMemBlitter& _textVideoMemBlitter) override; - void dbgTextRenderBegin(TextVideoMemBlitter& _blitter) override + void dbgTextRenderBegin(TextVideoMemBlitter& _blitter, FrameBufferHandle _handle) override { - const uint32_t width = m_backBuffer.m_width; - const uint32_t height = m_backBuffer.m_height; + m_dbgTextFbh = _handle; - setFrameBuffer(BGFX_INVALID_HANDLE); + const FrameBufferVK& frameBuffer = getFrameBuffer(_handle); + const uint32_t width = frameBuffer.m_width; + const uint32_t height = frameBuffer.m_height; + + setFrameBuffer(_handle); VkViewport vp; vp.x = 0.0f; @@ -3123,8 +3114,10 @@ VK_IMPORT_DEVICE { const uint32_t numVertices = _numIndices*4/6; + FrameBufferVK& frameBuffer = getFrameBuffer(m_dbgTextFbh); + if (0 < numVertices - && m_backBuffer.isRenderable() ) + && frameBuffer.isRenderable() ) { m_indexBuffers[_blitter.m_ib->handle.idx].update(m_commandBuffer, 0, _numIndices*2, _blitter.m_ib->data, true); m_vertexBuffers[_blitter.m_vb->handle.idx].update(m_commandBuffer, 0, numVertices*_blitter.m_layout.m_stride, _blitter.m_vb->data, true); @@ -3132,12 +3125,12 @@ VK_IMPORT_DEVICE VkRenderPassBeginInfo rpbi; rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; rpbi.pNext = NULL; - rpbi.renderPass = m_backBuffer.m_renderPass; - rpbi.framebuffer = m_backBuffer.m_currentFramebuffer; + rpbi.renderPass = frameBuffer.m_renderPass; + rpbi.framebuffer = frameBuffer.m_currentFramebuffer; rpbi.renderArea.offset.x = 0; rpbi.renderArea.offset.y = 0; - rpbi.renderArea.extent.width = m_backBuffer.m_width; - rpbi.renderArea.extent.height = m_backBuffer.m_height; + rpbi.renderArea.extent.width = frameBuffer.m_width; + rpbi.renderArea.extent.height = frameBuffer.m_height; rpbi.clearValueCount = 0; rpbi.pClearValues = NULL; @@ -3175,7 +3168,7 @@ VK_IMPORT_DEVICE m_frameBuffers[ii].postReset(); } - if (m_resolution.reset & BGFX_RESET_CAPTURE) + if (m_reset & BGFX_RESET_CAPTURE) { const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(m_backBuffer.m_swapChain.m_colorFormat) ); const uint32_t pitch = m_backBuffer.m_width * bpp / 8; @@ -3190,16 +3183,16 @@ VK_IMPORT_DEVICE VK_CHECK(createReadbackBuffer(m_captureSize, &m_captureBuffer, &m_captureMemory) ); } - g_callback->captureBegin(m_resolution.width, m_resolution.height, pitch, m_resolution.formatColor, false); + g_callback->captureBegin(m_mainSwapChain.width, m_mainSwapChain.height, pitch, m_mainSwapChain.formatColor, false); } } - bool updateResolution(const Resolution& _resolution) + bool updateResolution(const SwapChain& _swapChain, uint32_t _reset) { - const bool suspended = !!(_resolution.reset & BGFX_RESET_SUSPEND); + const bool suspended = !!(_reset & BGFX_RESET_SUSPEND); float maxAnisotropy = 1.0f; - if (!!(_resolution.reset & BGFX_RESET_MAXANISOTROPY) ) + if (!!(_reset & BGFX_RESET_MAXANISOTROPY) ) { maxAnisotropy = m_deviceProperties.limits.maxSamplerAnisotropy; } @@ -3211,7 +3204,7 @@ VK_IMPORT_DEVICE m_samplerBorderColorCache.invalidate(); } - bool depthClamp = m_deviceFeatures.depthClamp && !!(_resolution.reset & BGFX_RESET_DEPTH_CLAMP); + bool depthClamp = m_deviceFeatures.depthClamp && !!(_reset & BGFX_RESET_DEPTH_CLAMP); if (m_depthClamp != depthClamp) { @@ -3219,13 +3212,13 @@ VK_IMPORT_DEVICE m_pipelineStateCache.invalidate(); } - if (NULL == m_backBuffer.m_nwh) + if (!m_backBuffer.isSwapChain() ) { - if (m_resolution.width != _resolution.width - || m_resolution.height != _resolution.height) + if (m_mainSwapChain.width != _swapChain.width + || m_mainSwapChain.height != _swapChain.height) { - m_resolution.width = _resolution.width; - m_resolution.height = _resolution.height; + m_mainSwapChain.width = _swapChain.width; + m_mainSwapChain.height = _swapChain.height; for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) { @@ -3244,62 +3237,56 @@ VK_IMPORT_DEVICE ); if (m_swapchainMaintenance1Supported - && !!((_resolution.reset ^ m_resolution.reset) & BGFX_RESET_VSYNC) ) + && !!((_reset ^ m_reset) & BGFX_RESET_VSYNC) ) { - m_resolution.reset = 0 - | (m_resolution.reset & ~BGFX_RESET_VSYNC) - | ( _resolution.reset & BGFX_RESET_VSYNC) + m_reset = 0 + | (m_reset & ~BGFX_RESET_VSYNC) + | ( _reset & BGFX_RESET_VSYNC) ; + const bool vsync = !!(m_reset & BGFX_RESET_VSYNC); + for (uint16_t ii = 0; ii < m_numWindows; ++ii) { - FrameBufferVK& fb = isValid(m_windows[ii]) - ? m_frameBuffers[m_windows[ii].idx] - : m_backBuffer - ; - - fb.m_swapChain.m_resolution.reset = 0 - | (fb.m_swapChain.m_resolution.reset & ~BGFX_RESET_VSYNC) - | ( _resolution.reset & BGFX_RESET_VSYNC) - ; + getFrameBuffer(m_windows[ii]).m_swapChain.m_vsync = vsync; } maskFlags &= ~BGFX_RESET_VSYNC; } if (false - || m_resolution.formatColor != _resolution.formatColor - || m_resolution.formatDepthStencil != _resolution.formatDepthStencil - || m_resolution.width != _resolution.width - || m_resolution.height != _resolution.height - || (m_resolution.reset&maskFlags) != (_resolution.reset&maskFlags) + || m_mainSwapChain.formatColor != _swapChain.formatColor + || m_mainSwapChain.formatDepthStencil != _swapChain.formatDepthStencil + || m_mainSwapChain.width != _swapChain.width + || m_mainSwapChain.height != _swapChain.height + || m_mainSwapChain.nwh != _swapChain.nwh + || m_mainSwapChain.ndt != _swapChain.ndt + || (m_reset&maskFlags) != (_reset&maskFlags) || m_backBuffer.m_swapChain.m_needToRecreateSurface || m_backBuffer.m_swapChain.m_needToRecreateSwapchain ) { - uint32_t flags = _resolution.reset & (~BGFX_RESET_INTERNAL_FORCE); + uint32_t flags = _reset & (~BGFX_RESET_INTERNAL_FORCE); - if (m_backBuffer.m_nwh != g_platformData.nwh) + if (m_backBuffer.m_nwh != m_mainSwapChain.nwh) { - m_backBuffer.m_nwh = g_platformData.nwh; + m_backBuffer.m_nwh = m_mainSwapChain.nwh; } - m_resolution = _resolution; - m_resolution.reset = flags; + m_mainSwapChain = _swapChain; + m_reset = flags; - m_textVideoMem.resize(false, _resolution.width, _resolution.height); + m_textVideoMem.resize(false, _swapChain.width, _swapChain.height); m_textVideoMem.clear(); preReset(); - m_backBuffer.update(m_commandBuffer, m_resolution); + m_backBuffer.update(m_commandBuffer, m_mainSwapChain); // Update the resolution again here, as the actual width and height // is now final (as it was potentially clamped by the Vulkan driver). - m_resolution.width = m_backBuffer.m_width; - m_resolution.height = m_backBuffer.m_height; + m_mainSwapChain.width = m_backBuffer.m_width; + m_mainSwapChain.height = m_backBuffer.m_height; - // Propagate reset flags (e.g. BGFX_RESET_VSYNC) to secondary window swapchains, - // otherwise they'd keep their original present mode and ignore the reset. for (uint16_t ii = 0; ii < m_numWindows; ++ii) { if (!isValid(m_windows[ii]) ) @@ -3308,10 +3295,8 @@ VK_IMPORT_DEVICE } FrameBufferVK& fb = m_frameBuffers[m_windows[ii].idx]; - Resolution fbResolution = m_resolution; - fbResolution.width = fb.m_width; - fbResolution.height = fb.m_height; - fb.update(m_commandBuffer, fbResolution); + const SwapChain desc = fb.m_swapChain.m_desc; + fb.update(m_commandBuffer, desc); } postReset(); @@ -3342,23 +3327,31 @@ VK_IMPORT_DEVICE setShaderUniform(_flags, _regIndex, _val, _numRegs); } + FrameBufferVK& getFrameBuffer(FrameBufferHandle _fbh) + { + return isValid(_fbh) + ? m_frameBuffers[_fbh.idx] + : m_backBuffer + ; + } + + const FrameBufferVK& getFrameBuffer(FrameBufferHandle _fbh) const + { + return isValid(_fbh) + ? m_frameBuffers[_fbh.idx] + : m_backBuffer + ; + } + void setFrameBuffer(FrameBufferHandle _fbh) { BGFX_PROFILER_SCOPE("RendererContextVK::setFrameBuffer()", kColorFrame); - FrameBufferVK& newFrameBuffer = isValid(_fbh) - ? m_frameBuffers[_fbh.idx] - : m_backBuffer - ; + FrameBufferVK& newFrameBuffer = getFrameBuffer(_fbh); + FrameBufferVK& oldFrameBuffer = getFrameBuffer(m_fbh); - FrameBufferVK& oldFrameBuffer = isValid(m_fbh) - ? m_frameBuffers[m_fbh.idx] - : m_backBuffer - ; - - if (NULL == oldFrameBuffer.m_nwh - && m_fbh.idx != _fbh.idx) - { + if (!oldFrameBuffer.isSwapChain() + && m_fbh.idx != _fbh.idx) { oldFrameBuffer.resolve(); for (uint8_t ii = 0, num = oldFrameBuffer.m_num; ii < num; ++ii) @@ -3383,15 +3376,15 @@ VK_IMPORT_DEVICE } } - if (!isValid(_fbh) - && NULL == m_backBuffer.m_nwh) + if (!newFrameBuffer.isSwapChain() ) { - m_fbh = _fbh; - return; - } + if (0 == newFrameBuffer.m_num + && !isValid(newFrameBuffer.m_depth) ) + { + m_fbh = _fbh; + return; + } - if (NULL == newFrameBuffer.m_nwh) - { for (uint8_t ii = 0, num = newFrameBuffer.m_num; ii < num; ++ii) { TextureVK& texture = m_textures[newFrameBuffer.m_texture[ii].idx]; @@ -3412,11 +3405,17 @@ VK_IMPORT_DEVICE } else { + if (isValid(newFrameBuffer.m_swapChain.m_desc.depth) ) + { + TextureVK& texture = m_textures[newFrameBuffer.m_swapChain.m_desc.depth.idx]; + texture.setState( + m_commandBuffer + , VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL + ); + } + int64_t start = bx::getHPCounter(); - // Only block acquiring the main back buffer: window swap chains may not be - // served anymore (e.g. fully occluded window on Wayland compositors without - // fifo-v1) and must not stall the whole frame. - newFrameBuffer.acquire(m_commandBuffer, &newFrameBuffer == &m_backBuffer); + newFrameBuffer.acquire(m_commandBuffer, !isValid(_fbh) ); m_presentElapsed += bx::getHPCounter() - start; } @@ -3469,10 +3468,7 @@ VK_IMPORT_DEVICE bas->colorWriteMask = writeMask; } - const FrameBufferVK& frameBuffer = isValid(m_fbh) - ? m_frameBuffers[m_fbh.idx] - : m_backBuffer - ; + const FrameBufferVK& frameBuffer = getFrameBuffer(m_fbh); const uint32_t numAttachments = NULL == frameBuffer.m_nwh ? frameBuffer.m_num @@ -3860,13 +3856,13 @@ VK_IMPORT_DEVICE const VkFormat formats[2] = { swapChain.m_sci.imageFormat, - swapChain.m_backBufferDepthStencil.m_format + swapChain.m_depthStencilFormat }; const VkImageAspectFlags aspects[2] = { VK_IMAGE_ASPECT_COLOR_BIT, - swapChain.m_backBufferDepthStencil.m_aspectFlags + swapChain.m_depthStencilAspect }; const bool resolve[2] = @@ -4108,10 +4104,7 @@ VK_IMPORT_DEVICE } } - const FrameBufferVK& frameBuffer = isValid(m_fbh) - ? m_frameBuffers[m_fbh.idx] - : m_backBuffer - ; + const FrameBufferVK& frameBuffer = getFrameBuffer(m_fbh); bx::HashMurmur2A murmur; murmur.begin(); @@ -4784,10 +4777,7 @@ VK_IMPORT_DEVICE bgfx::TextureFormat::Enum mrtFormat[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; VkImageAspectFlags depthAspectMask; - const FrameBufferVK& fb = isValid(m_fbh) - ? m_frameBuffers[m_fbh.idx] - : m_backBuffer - ; + const FrameBufferVK& fb = getFrameBuffer(m_fbh); if (NULL == fb.m_nwh) { @@ -4803,7 +4793,7 @@ VK_IMPORT_DEVICE { numMrt = 1; mrtFormat[0] = fb.m_swapChain.m_colorFormat; - depthAspectMask = fb.m_swapChain.m_backBufferDepthStencil.m_aspectFlags; + depthAspectMask = fb.m_swapChain.m_depthStencilAspect; } VkClearAttachment attachments[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS + 1]; @@ -5107,6 +5097,8 @@ VK_IMPORT_DEVICE FrameBufferVK m_backBuffer; + FrameBufferHandle m_dbgTextFbh; + uint16_t m_numWindows; FrameBufferHandle m_windows[BGFX_CONFIG_MAX_FRAME_BUFFERS]; int64_t m_presentElapsed; @@ -5164,7 +5156,8 @@ VK_IMPORT_DEVICE StateCacheT m_samplerBorderColorCache; StateCacheLru m_imageViewCache; - Resolution m_resolution; + SwapChain m_mainSwapChain; + uint32_t m_reset; float m_maxAnisotropy; bool m_depthClamp; bool m_wireframe; @@ -7866,7 +7859,7 @@ VK_DESTROY } } - VkResult SwapChainVK::create(VkCommandBuffer _commandBuffer, void* _nwh, const Resolution& _resolution) + VkResult SwapChainVK::create(VkCommandBuffer _commandBuffer, void* _nwh, const SwapChain& _desc) { struct ErrorState { @@ -7888,8 +7881,9 @@ VK_DESTROY return result; } - m_nwh = _nwh; - m_resolution = _resolution; + m_nwh = _nwh; + m_desc = _desc; + m_vsync = !!(s_renderVK->m_reset & BGFX_RESET_VSYNC); m_queue = s_renderVK->m_globalQueue; @@ -8007,42 +8001,48 @@ VK_DESTROY m_nwh = NULL; } - void SwapChainVK::update(VkCommandBuffer _commandBuffer, void* _nwh, const Resolution& _resolution) + void SwapChainVK::update(VkCommandBuffer _commandBuffer, void* _nwh, const SwapChain& _desc) { BGFX_PROFILER_SCOPE("SwapChainVK::update", kColorFrame); const VkPhysicalDevice physicalDevice = s_renderVK->m_physicalDevice; - const uint64_t recreateSurfaceMask = BGFX_RESET_HIDPI; - const uint64_t recreateSwapchainMask = 0 - | BGFX_RESET_SRGB_BACKBUFFER - | (s_renderVK->m_swapchainMaintenance1Supported ? BGFX_RESET_NONE : BGFX_RESET_VSYNC) + const uint64_t recreateSurfaceMask = BGFX_SWAP_CHAIN_HIDPI; + const uint64_t recreateSwapchainMask = BGFX_SWAP_CHAIN_SRGB_BACKBUFFER; + const uint64_t recreateAttachmentsMask = BGFX_SWAP_CHAIN_MSAA_MASK; + + const bool vsync = !!(s_renderVK->m_reset & BGFX_RESET_VSYNC); + const bool vsyncChanged = false + || (m_vsync != vsync && !s_renderVK->m_swapchainMaintenance1Supported) ; - const uint64_t recreateAttachmentsMask = BGFX_RESET_MSAA_MASK; const bool recreateSurface = false || m_needToRecreateSurface || m_nwh != _nwh - || (m_resolution.reset & recreateSurfaceMask) != (_resolution.reset & recreateSurfaceMask) + || (m_desc.flags & recreateSurfaceMask) != (_desc.flags & recreateSurfaceMask) ; const bool recreateSwapchain = false || m_needToRecreateSwapchain - || m_resolution.formatColor != _resolution.formatColor - || m_resolution.formatDepthStencil != _resolution.formatDepthStencil - || m_resolution.width != _resolution.width - || m_resolution.height != _resolution.height - || (m_resolution.reset & recreateSwapchainMask) != (_resolution.reset & recreateSwapchainMask) + || m_desc.formatColor != _desc.formatColor + || m_desc.formatDepthStencil != _desc.formatDepthStencil + || m_desc.width != _desc.width + || m_desc.height != _desc.height + || (m_desc.flags & recreateSwapchainMask) != (_desc.flags & recreateSwapchainMask) + || vsyncChanged || recreateSurface ; + // A different user depth (or none) is a different depth attachment. const bool recreateAttachments = false - || (m_resolution.reset & recreateAttachmentsMask) != (_resolution.reset & recreateAttachmentsMask) + || (m_desc.flags & recreateAttachmentsMask) != (_desc.flags & recreateAttachmentsMask) + || m_desc.depth.idx != _desc.depth.idx || recreateSwapchain ; - m_nwh = _nwh; - m_resolution = _resolution; + m_nwh = _nwh; + m_desc = _desc; + m_vsync = vsync; if (recreateAttachments) { @@ -8082,25 +8082,25 @@ VK_DESTROY ; const uint32_t width = bx::clamp( - m_resolution.width + m_desc.width , surfaceCapabilities.minImageExtent.width , surfaceCapabilities.maxImageExtent.width ); const uint32_t height = bx::clamp( - m_resolution.height + m_desc.height , surfaceCapabilities.minImageExtent.height , surfaceCapabilities.maxImageExtent.height ); - // swapchain can't have size 0 - // on some platforms this happens when minimized - if (width == 0 - || height == 0 + if (0 == width + || 0 == height || VK_SUCCESS != result || !surfaceCapsSane) { m_sci.oldSwapchain = VK_NULL_HANDLE; s_renderVK->kick(true); + + m_needToRecreateSwapchain = true; return; } @@ -8161,7 +8161,7 @@ VK_DESTROY sci.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR; sci.pNext = NULL; sci.flags = 0; - sci.display = (wl_display*)g_platformData.ndt; + sci.display = (wl_display*)m_desc.ndt; sci.surface = (wl_surface*)m_nwh; result = vkCreateWaylandSurfaceKHR(instance, &sci, allocatorCb, &m_surface); BX_WARN(VK_SUCCESS == result, "vkCreateWaylandSurfaceKHR failed %d: %s.", result, getName(result) ); @@ -8178,7 +8178,7 @@ VK_DESTROY sci.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; sci.pNext = NULL; sci.flags = 0; - sci.dpy = (Display*)g_platformData.ndt; + sci.dpy = (Display*)m_desc.ndt; sci.window = (Window)m_nwh; result = vkCreateXlibSurfaceKHR(instance, &sci, allocatorCb, &m_surface); BX_WARN(VK_SUCCESS == result, "vkCreateXlibSurfaceKHR failed %d: %s.", result, getName(result) ); @@ -8203,7 +8203,7 @@ VK_DESTROY sci.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; sci.pNext = NULL; sci.flags = 0; - sci.connection = XGetXCBConnection( (Display*)g_platformData.ndt); + sci.connection = XGetXCBConnection( (Display*)m_desc.ndt); if (NULL != sci.connection) { sci.window = bx::narrowCast(uintptr_t(m_nwh) ); @@ -8243,7 +8243,7 @@ VK_DESTROY return result; } - if (m_resolution.reset & BGFX_RESET_HIDPI) + if (m_desc.flags & BGFX_SWAP_CHAIN_HIDPI) { layer.contentsScale = [window backingScaleFactor]; } @@ -8343,12 +8343,12 @@ VK_DESTROY return VK_ERROR_INITIALIZATION_FAILED; } - const uint32_t swapBufferCount = bx::clamp(m_resolution.numBackBuffers, minSwapBufferCount, maxSwapBufferCount); + const uint32_t swapBufferCount = bx::clamp(m_desc.numBackBuffers, minSwapBufferCount, maxSwapBufferCount); const VkColorSpaceKHR surfaceColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - const bool srgb = !!(m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER); - m_colorFormat = m_resolution.formatColor; + const bool srgb = !!(m_desc.flags & BGFX_SWAP_CHAIN_SRGB_BACKBUFFER); + m_colorFormat = m_desc.formatColor; m_depthFormat = bgfx::TextureFormat::UnknownDepth; if (TextureFormat::Count == m_colorFormat) @@ -8363,20 +8363,20 @@ VK_DESTROY ; const uint32_t width = bx::clamp( - m_resolution.width + m_desc.width , surfaceCapabilities.minImageExtent.width , surfaceCapabilities.maxImageExtent.width ); const uint32_t height = bx::clamp( - m_resolution.height + m_desc.height , surfaceCapabilities.minImageExtent.height , surfaceCapabilities.maxImageExtent.height ); - if (width != m_resolution.width || height != m_resolution.height) + if (width != m_desc.width || height != m_desc.height) { BX_TRACE("Clamped swapchain resolution from %dx%d to %dx%d" - , m_resolution.width - , m_resolution.height + , m_desc.width + , m_desc.height , width , height ); @@ -8384,7 +8384,7 @@ VK_DESTROY VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - if (m_resolution.reset & BGFX_RESET_TRANSPARENT_BACKBUFFER) + if (m_desc.flags & BGFX_SWAP_CHAIN_TRANSPARENT_BACKBUFFER) { if (surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) { @@ -8413,7 +8413,7 @@ VK_DESTROY m_presentModeWithVSyncIdx = findPresentMode(true); m_presentModeWithoutVSyncIdx = findPresentMode(false); - const bool vsync = !!(m_resolution.reset & BGFX_RESET_VSYNC); + const bool vsync = m_vsync; const uint32_t presentModeIdx = vsync ? m_presentModeWithVSyncIdx : m_presentModeWithoutVSyncIdx @@ -8597,7 +8597,7 @@ VK_DESTROY VkResult result = VK_SUCCESS; - const uint32_t samplerIndex = (m_resolution.reset & BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT; + const uint32_t samplerIndex = (m_desc.flags & BGFX_SWAP_CHAIN_MSAA_MASK) >> BGFX_SWAP_CHAIN_MSAA_SHIFT; const uint64_t textureFlags = (uint64_t(samplerIndex + 1) << BGFX_TEXTURE_RT_MSAA_SHIFT) | BGFX_TEXTURE_RT | BGFX_TEXTURE_RT_WRITE_ONLY; m_sampler = s_msaa[samplerIndex]; @@ -8606,14 +8606,34 @@ VK_DESTROY : BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER ; - if (bimg::isDepth(bimg::TextureFormat::Enum(m_resolution.formatDepthStencil) ) ) + if (isValid(m_desc.depth) ) + { + TextureVK& texture = s_renderVK->m_textures[m_desc.depth.idx]; + + result = texture.createView(0, 1, 0, 1 + , VK_IMAGE_VIEW_TYPE_2D + , texture.m_aspectFlags + , true + , &m_backBufferDepthStencilImageView + ); + + if (VK_SUCCESS != result) + { + BX_TRACE("Create swapchain error: creating shared depth stencil image view failed %d: %s.", result, getName(result) ); + return result; + } + + m_depthStencilFormat = texture.m_format; + m_depthStencilAspect = texture.m_aspectFlags; + } + else if (bimg::isDepth(bimg::TextureFormat::Enum(m_desc.formatDepthStencil) ) ) { // the spec guarantees that at least one of D24S8 and D32FS8 is supported VkFormat depthFormat = VK_FORMAT_D32_SFLOAT_S8_UINT; - if (g_caps.formats[m_resolution.formatDepthStencil] & requiredCaps) + if (g_caps.formats[m_desc.formatDepthStencil] & requiredCaps) { - depthFormat = s_textureFormat[m_resolution.formatDepthStencil].m_fmtDsv; + depthFormat = s_textureFormat[m_desc.formatDepthStencil].m_fmtDsv; } else if (g_caps.formats[TextureFormat::D24S8] & requiredCaps) { @@ -8647,34 +8667,37 @@ VK_DESTROY return result; } - if (m_sampler.Count > 1) - { - result = m_backBufferColorMsaa.create( - _commandBuffer - , m_sci.imageExtent.width - , m_sci.imageExtent.height - , textureFlags - , m_sci.imageFormat - ); + m_depthStencilFormat = m_backBufferDepthStencil.m_format; + m_depthStencilAspect = m_backBufferDepthStencil.m_aspectFlags; + } - if (VK_SUCCESS != result) - { - BX_TRACE("Create swapchain error: creating MSAA color image failed %d: %s.", result, getName(result) ); - return result; - } - - result = m_backBufferColorMsaa.createView(0, 1, 0, 1 - , VK_IMAGE_VIEW_TYPE_2D - , m_backBufferColorMsaa.m_aspectFlags - , true - , &m_backBufferColorMsaaImageView + if (m_sampler.Count > 1) + { + result = m_backBufferColorMsaa.create( + _commandBuffer + , m_sci.imageExtent.width + , m_sci.imageExtent.height + , textureFlags + , m_sci.imageFormat ); - if (VK_SUCCESS != result) - { - BX_TRACE("Create swapchain error: creating MSAA color image view failed %d: %s.", result, getName(result) ); - return result; - } + if (VK_SUCCESS != result) + { + BX_TRACE("Create swapchain error: creating MSAA color image failed %d: %s.", result, getName(result) ); + return result; + } + + result = m_backBufferColorMsaa.createView(0, 1, 0, 1 + , VK_IMAGE_VIEW_TYPE_2D + , m_backBufferColorMsaa.m_aspectFlags + , true + , &m_backBufferColorMsaaImageView + ); + + if (VK_SUCCESS != result) + { + BX_TRACE("Create swapchain error: creating MSAA color image view failed %d: %s.", result, getName(result) ); + return result; } } @@ -8690,6 +8713,9 @@ VK_DESTROY m_backBufferDepthStencil.destroy(); m_backBufferColorMsaa.destroy(); + + m_depthStencilFormat = VK_FORMAT_UNDEFINED; + m_depthStencilAspect = 0; } VkResult SwapChainVK::createFrameBuffer() @@ -8846,7 +8872,7 @@ VK_DESTROY result = vkAcquireNextImageKHR( device , m_swapChain - , _block ? UINT64_MAX : 0 + , _block ? UINT64_MAX : 1000000 , m_lastImageAcquiredSemaphore , VK_NULL_HANDLE , &m_backBufferColorIdx @@ -8856,9 +8882,6 @@ VK_DESTROY if (!_block && (VK_NOT_READY == result || VK_TIMEOUT == result) ) { - // No image available without blocking, e.g. a fully occluded window the - // compositor stopped serving; skip this swap chain for this frame instead - // of stalling all swap chains. The semaphore was not used, undo the rotation. m_currentSemaphore = (m_currentSemaphore + kMaxBackBuffers - 1) % kMaxBackBuffers; return false; } @@ -8942,7 +8965,7 @@ VK_DESTROY VkSwapchainPresentModeInfoEXT presentModeInfo; if (s_renderVK->m_swapchainMaintenance1Supported) { - const uint32_t presentModeIdx = !!(m_resolution.reset & BGFX_RESET_VSYNC) + const uint32_t presentModeIdx = m_vsync ? m_presentModeWithVSyncIdx : m_presentModeWithoutVSyncIdx; ; @@ -9045,24 +9068,11 @@ VK_DESTROY postReset(); } - VkResult FrameBufferVK::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _colorFormat, TextureFormat::Enum _depthFormat) + VkResult FrameBufferVK::create(uint16_t _denseIdx, const SwapChain& _desc) { BGFX_PROFILER_SCOPE("FrameBufferVK::create", kColorFrame); - VkResult result = VK_SUCCESS; - - Resolution resolution = s_renderVK->m_resolution; - resolution.formatColor = TextureFormat::Count == _colorFormat ? resolution.formatColor : _colorFormat; - resolution.formatDepthStencil = TextureFormat::Count == _depthFormat ? resolution.formatDepthStencil : _depthFormat; - resolution.width = _width; - resolution.height = _height; - - if (_denseIdx != UINT16_MAX) - { - resolution.reset &= ~BGFX_RESET_MSAA_MASK; - } - - result = m_swapChain.create(s_renderVK->m_commandBuffer, _nwh, resolution); + VkResult result = m_swapChain.create(s_renderVK->m_commandBuffer, _desc.nwh, _desc); if (VK_SUCCESS != result) { @@ -9077,7 +9087,7 @@ VK_DESTROY } m_denseIdx = _denseIdx; - m_nwh = _nwh; + m_nwh = _desc.nwh; m_width = m_swapChain.m_sci.imageExtent.width; m_height = m_swapChain.m_sci.imageExtent.height; m_sampler = m_swapChain.m_sampler; @@ -9178,13 +9188,13 @@ VK_DESTROY } } - void FrameBufferVK::update(VkCommandBuffer _commandBuffer, const Resolution& _resolution) + void FrameBufferVK::update(VkCommandBuffer _commandBuffer, const SwapChain& _desc) { BGFX_PROFILER_SCOPE("FrameBufferVK::update", kColorResource); - m_swapChain.update(_commandBuffer, m_nwh, _resolution); + m_swapChain.update(_commandBuffer, m_nwh, _desc); VK_CHECK(s_renderVK->getRenderPass(m_swapChain, 0, &m_renderPass, &m_renderPassHashKey) ); - // Don't believe the passed Resolution, as the Vulkan driver might have + // Don't believe the passed size, as the Vulkan driver might have // specified another resolution, which we had to obey. m_width = m_swapChain.m_sci.imageExtent.width; m_height = m_swapChain.m_sci.imageExtent.height; @@ -9258,14 +9268,12 @@ VK_DESTROY BX_ASSERT(NULL != m_nwh, "FrameBufferVK::acquire is only valid for swap-chain framebuffers."); BGFX_PROFILER_SCOPE("FrameBufferVK::acquire", kColorFrame); - // Window frame buffers are not recreated by updateResolution like the main back - // buffer is, so recreate here when the swap chain was flagged, e.g. with - // VK_SUBOPTIMAL_KHR after the window moved to another display. - if (this != &s_renderVK->m_backBuffer - && VK_NULL_HANDLE != m_swapChain.m_swapChain + if ( UINT16_MAX != m_denseIdx + && VK_NULL_HANDLE != m_swapChain.m_surface && (m_swapChain.m_needToRecreateSwapchain || m_swapChain.m_needToRecreateSurface) ) { - update(_commandBuffer, m_swapChain.m_resolution); + const SwapChain desc = m_swapChain.m_desc; + update(_commandBuffer, desc); // update may kick the queue and rotate the command buffer, refresh the local handle _commandBuffer = s_renderVK->m_commandBuffer; @@ -10020,7 +10028,7 @@ VK_DESTROY void RendererContextVK::submit(Frame* _render, const ClearQuad& /*_clearQuad*/, const MipGen& /*_mipGen*/, TextVideoMemBlitter& _textVideoMemBlitter) { if (m_lost - || updateResolution(_render->m_resolution) ) + || updateResolution(_render->m_mainSwapChain, _render->m_reset) ) { return; } @@ -10244,10 +10252,7 @@ VK_DESTROY profiler.begin(view); - const FrameBufferVK& fb = isValid(m_fbh) - ? m_frameBuffers[m_fbh.idx] - : m_backBuffer - ; + const FrameBufferVK& fb = getFrameBuffer(m_fbh); isFrameBufferValid = fb.isRenderable(); @@ -10316,7 +10321,7 @@ VK_DESTROY { numMrt = 1; mrtFormat[0] = fb.m_swapChain.m_colorFormat; - depthAspectMask = fb.m_swapChain.m_backBufferDepthStencil.m_aspectFlags; + depthAspectMask = fb.m_swapChain.m_depthStencilAspect; } VkClearValue clearValues[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS + 1]; @@ -11209,12 +11214,12 @@ VK_DESTROY , double(presentMax)*toMs ); - const uint32_t msaa = (m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + const uint32_t msaa = (m_mainSwapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT; tvm.printf(10, pos++, 0x8b, " Reset flags: [%c] vsync, [%c] MSAAx%d, [%c] MaxAnisotropy " - , !!(m_resolution.reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' + , !!(m_reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' , 0 != msaa ? '\xfe' : ' ' , 1<m_debugFrameBuffer, _render->m_debugTextScale); BGFX_VK_PROFILER_END(); } @@ -11295,7 +11300,7 @@ VK_DESTROY { BGFX_VK_PROFILER_BEGIN_LITERAL("debugtext", kColorFrame); - dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem); + dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem, _render->m_debugFrameBuffer, _render->m_debugTextScale); BGFX_VK_PROFILER_END(); } @@ -11313,10 +11318,7 @@ VK_DESTROY { for (uint16_t ii = 0; ii < m_numWindows; ++ii) { - FrameBufferVK& fb = isValid(m_windows[ii]) - ? m_frameBuffers[m_windows[ii].idx] - : m_backBuffer - ; + FrameBufferVK& fb = getFrameBuffer(m_windows[ii]); if (fb.m_needPresent) { diff --git a/src/renderer_vk.h b/src/renderer_vk.h index 77ff0e8e7..9cdf8cf86 100644 --- a/src/renderer_vk.h +++ b/src/renderer_vk.h @@ -767,20 +767,23 @@ VK_DESTROY_FUNC(DescriptorSet); { SwapChainVK() : m_nwh(NULL) + , m_vsync(false) , m_swapChain(VK_NULL_HANDLE) , m_lastImageRenderedSemaphore(VK_NULL_HANDLE) , m_lastImageAcquiredSemaphore(VK_NULL_HANDLE) , m_needPresent(false) , m_backBufferDepthStencilImageView(VK_NULL_HANDLE) + , m_depthStencilFormat(VK_FORMAT_UNDEFINED) + , m_depthStencilAspect(0) , m_backBufferColorMsaaImageView(VK_NULL_HANDLE) { } - VkResult create(VkCommandBuffer _commandBuffer, void* _nwh, const Resolution& _resolution); + VkResult create(VkCommandBuffer _commandBuffer, void* _nwh, const SwapChain& _desc); void destroy(); - void update(VkCommandBuffer _commandBuffer, void* _nwh, const Resolution& _resolution); + void update(VkCommandBuffer _commandBuffer, void* _nwh, const SwapChain& _desc); VkResult createSurface(); VkResult createSwapChain(); @@ -806,7 +809,9 @@ VK_DESTROY_FUNC(DescriptorSet); VkSwapchainCreateInfoKHR m_sci; void* m_nwh; - Resolution m_resolution; + SwapChain m_desc; + + bool m_vsync; TextureFormat::Enum m_colorFormat; TextureFormat::Enum m_depthFormat; @@ -837,6 +842,8 @@ VK_DESTROY_FUNC(DescriptorSet); TextureVK m_backBufferDepthStencil; VkImageView m_backBufferDepthStencilImageView; + VkFormat m_depthStencilFormat; + VkImageAspectFlags m_depthStencilAspect; TextureVK m_backBufferColorMsaa; VkImageView m_backBufferColorMsaaImageView; @@ -863,10 +870,10 @@ VK_DESTROY_FUNC(DescriptorSet); } void create(uint8_t _num, const Attachment* _attachment); - VkResult create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format = TextureFormat::Count, TextureFormat::Enum _depthFormat = TextureFormat::Count); + VkResult create(uint16_t _denseIdx, const SwapChain& _desc); uint16_t destroy(); - void update(VkCommandBuffer _commandBuffer, const Resolution& _resolution); + void update(VkCommandBuffer _commandBuffer, const SwapChain& _desc); void preReset(); void postReset(); @@ -882,6 +889,11 @@ VK_DESTROY_FUNC(DescriptorSet); bool isRenderable() const; + bool isSwapChain() const + { + return NULL != m_nwh; + } + TextureHandle m_texture[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; TextureHandle m_depth; uint32_t m_width; diff --git a/src/renderer_webgpu.cpp b/src/renderer_webgpu.cpp index 40bc7bfd6..930f57057 100644 --- a/src/renderer_webgpu.cpp +++ b/src/renderer_webgpu.cpp @@ -1006,7 +1006,7 @@ WGPU_IMPORT // m_fbh = BGFX_INVALID_HANDLE; bx::memSet(m_uniforms, 0, sizeof(m_uniforms) ); - bx::memSet(&m_resolution, 0, sizeof(m_resolution) ); + bx::memSet(&m_mainSwapChain, 0, sizeof(m_mainSwapChain) ); if (_init.debug || _init.profile) @@ -1018,7 +1018,7 @@ WGPU_IMPORT || NULL != m_renderDocDll ); - const bool headless = NULL == g_platformData.nwh; + const bool headless = NULL == _init.swapChain.nwh; bool imported = true; @@ -1505,9 +1505,9 @@ WGPU_IMPORT BX_TRACE(""); { - m_maxFrameLatency = _init.resolution.maxFrameLatency == 0 + m_maxFrameLatency = _init.swapChain.maxFrameLatency == 0 ? BGFX_CONFIG_MAX_FRAME_LATENCY - : _init.resolution.maxFrameLatency + : _init.swapChain.maxFrameLatency ; m_cmd.init(m_device); @@ -1516,24 +1516,17 @@ WGPU_IMPORT } { - m_resolution = _init.resolution; - m_resolution.reset &= ~BGFX_RESET_INTERNAL_FORCE; + m_mainSwapChain = _init.swapChain; + m_reset &= ~BGFX_RESET_INTERNAL_FORCE; - m_textVideoMem.resize(false, _init.resolution.width, _init.resolution.height); + m_textVideoMem.resize(false, _init.swapChain.width, _init.swapChain.height); m_textVideoMem.clear(); m_numWindows = 0; if (!headless) { - m_backBuffer.create( - UINT16_MAX - , g_platformData.nwh - , m_resolution.width - , m_resolution.height - , m_resolution.formatColor - ); - + m_backBuffer.create(UINT16_MAX, m_mainSwapChain); m_windows[0] = BGFX_INVALID_HANDLE; m_numWindows++; @@ -1686,10 +1679,7 @@ WGPU_IMPORT for (uint16_t ii = 0; ii < m_numWindows; ++ii) { - FrameBufferWGPU& fb = isValid(m_windows[ii]) - ? m_frameBuffers[m_windows[ii].idx] - : m_backBuffer - ; + FrameBufferWGPU& fb = getFrameBuffer(m_windows[ii]); fb.present(); } @@ -2157,10 +2147,6 @@ WGPU_IMPORT release(mem); } - void overrideInternal(TextureHandle /*_handle*/, uintptr_t /*_ptr*/, uint16_t /*_layerIndex*/) override - { - } - uintptr_t getInternal(TextureHandle _handle) override { setGraphicsDebuggerPresent(true); @@ -2178,13 +2164,13 @@ WGPU_IMPORT m_frameBuffers[_handle.idx].create(_num, _attachment); } - void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat) override + void createFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override { for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii) { FrameBufferHandle handle = m_windows[ii]; if (isValid(handle) - && m_frameBuffers[handle.idx].m_swapChain.m_nwh == _nwh) + && m_frameBuffers[handle.idx].m_swapChain.m_nwh == _desc.nwh) { destroyFrameBuffer(handle); } @@ -2192,7 +2178,12 @@ WGPU_IMPORT uint16_t denseIdx = m_numWindows++; m_windows[denseIdx] = _handle; - m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _format, _depthFormat); + m_frameBuffers[_handle.idx].create(denseIdx, _desc); + } + + void resizeFrameBuffer(FrameBufferHandle _handle, const SwapChain& _desc) override + { + m_frameBuffers[_handle.idx].update(_desc); } void destroyFrameBuffer(FrameBufferHandle _handle) override @@ -2239,8 +2230,137 @@ WGPU_IMPORT m_uniformReg.remove(_handle); } - void requestScreenShot(FrameBufferHandle /*_handle*/, const char* /*_filePath*/) override + FrameBufferWGPU& getFrameBuffer(FrameBufferHandle _fbh) { + return isValid(_fbh) + ? m_frameBuffers[_fbh.idx] + : m_backBuffer + ; + } + + const FrameBufferWGPU& getFrameBuffer(FrameBufferHandle _fbh) const + { + return isValid(_fbh) + ? m_frameBuffers[_fbh.idx] + : m_backBuffer + ; + } + + void requestScreenShot(FrameBufferHandle _handle, const char* _filePath) override + { + const FrameBufferWGPU& frameBuffer = getFrameBuffer(_handle); + const SwapChainWGPU& swapChain = frameBuffer.m_swapChain; + + if (NULL == swapChain.m_texture + || !swapChain.m_readable) + { + BX_TRACE("Unable to capture screenshot %s.", _filePath); + return; + } + + const uint32_t width = swapChain.m_surfaceConfig.width; + const uint32_t height = swapChain.m_surfaceConfig.height; + + const TextureFormat::Enum format = TextureFormat::Enum(swapChain.m_desc.formatColor); + const uint8_t bpp = bimg::getBitsPerPixel(bimg::TextureFormat::Enum(format) ); + + const uint32_t dstPitch = width*bpp/8; + const uint32_t srcPitch = bx::alignUp(dstPitch, 256); + const uint32_t copySize = srcPitch*height; + + WGPUBufferDescriptor readTextureBufferDesc = + { + .nextInChain = NULL, + .label = toWGPUStringView("Screen Shot Buffer"), + .usage = 0 + | WGPUBufferUsage_MapRead + | WGPUBufferUsage_CopyDst + , + .size = copySize, + .mappedAtCreation = false, + }; + + WGPUBuffer readTextureBuffer = WGPU_CHECK(wgpuDeviceCreateBuffer(m_device, &readTextureBufferDesc) ); + + void* data = bx::alloc(g_allocator, dstPitch*height); + + s_done = false; + + m_cmd.copyTextureToBuffer( + { + .texture = swapChain.m_texture, + .mipLevel = 0, + .origin = + { + .x = 0, + .y = 0, + .z = 0, + }, + .aspect = WGPUTextureAspect_All, + }, + { + .layout = + { + .offset = 0, + .bytesPerRow = srcPitch, + .rowsPerImage = height, + }, + .buffer = readTextureBuffer, + }, + { + .width = width, + .height = height, + .depthOrArrayLayers = 1, + } + ); + + m_cmd.kick(); + m_cmd.wait(); + + ReadTexture readTexture = + { + .buffer = readTextureBuffer, + .size = copySize, + .data = data, + .dataPitch = dstPitch, + .pitch = srcPitch, + .height = height, + .width = width, + .stencilOffset = 0, + .stencilPitch = 0, + .texelSize = uint32_t(bpp/8), + }; + + WGPU_CHECK(wgpuBufferMapAsync( + readTextureBuffer + , WGPUMapMode_Read + , 0 + , copySize + , { + .nextInChain = NULL, + .mode = WGPUCallbackMode_AllowProcessEvents, + .callback = readTextureCb, + .userdata1 = &readTexture, + .userdata2 = &s_done, + }) ); + + while (!s_done) + { + wgpuInstanceProcessEvents(m_instance); + } + + g_callback->screenShot( + _filePath + , width + , height + , dstPitch + , format + , data + , dstPitch*height + , false + ); + + bx::free(g_allocator, data); } void updateViewName(ViewId _id, const char* _name) override @@ -2303,10 +2423,15 @@ WGPU_IMPORT void submit(Frame* _render, const ClearQuad& _clearQuad, const MipGen& _mipGen, TextVideoMemBlitter& _textVideoMemBlitter) override; - void dbgTextRenderBegin(TextVideoMemBlitter& _blitter) override + void dbgTextRenderBegin(TextVideoMemBlitter& _blitter, FrameBufferHandle _handle) override { - const uint32_t width = m_backBuffer.m_width; - const uint32_t height = m_backBuffer.m_height; + FrameBufferWGPU& frameBuffer = getFrameBuffer(_handle); + BX_ASSERT(frameBuffer.isSwapChain(), "Debug text target must be a window frame buffer."); + + const uint32_t width = frameBuffer.m_width; + const uint32_t height = frameBuffer.m_height; + + frameBuffer.m_needPresent = true; float proj[16]; bx::mtxOrtho(proj, 0.0f, (float)width, (float)height, 0.0f, 0.0f, 1000.0f, 0.0f, false); @@ -2343,7 +2468,7 @@ WGPU_IMPORT const RenderPipeline& pipeline = *getPipeline( _blitter.m_program - , BGFX_INVALID_HANDLE + , _handle , 1 , state , 0 @@ -2359,7 +2484,7 @@ WGPU_IMPORT WGPURenderPassColorAttachment colorAttachment = { .nextInChain = NULL, - .view = m_backBuffer.m_swapChain.m_textureView, + .view = frameBuffer.m_swapChain.m_textureView, .depthSlice = WGPU_DEPTH_SLICE_UNDEFINED, .resolveTarget = NULL, .loadOp = WGPULoadOp_Load, @@ -2550,7 +2675,7 @@ WGPU_IMPORT m_frameBuffers[ii].postReset(); } - if (m_resolution.reset & BGFX_RESET_CAPTURE) + if (m_reset & BGFX_RESET_CAPTURE) { } } @@ -2573,12 +2698,12 @@ WGPU_IMPORT m_bindGroupMap.clear(); } - bool updateResolution(const Resolution& _resolution) + bool updateResolution(const SwapChain& _swapChain, uint32_t _reset) { - const bool suspended = !!(_resolution.reset & BGFX_RESET_SUSPEND); + const bool suspended = !!(_reset & BGFX_RESET_SUSPEND); uint16_t maxAnisotropy = 1; - if (!!(_resolution.reset & BGFX_RESET_MAXANISOTROPY) ) + if (!!(_reset & BGFX_RESET_MAXANISOTROPY) ) { maxAnisotropy = 16; } @@ -2589,7 +2714,7 @@ WGPU_IMPORT m_samplerStateCache.invalidate(); } - const bool depthClamp = !!(_resolution.reset & BGFX_RESET_DEPTH_CLAMP); + const bool depthClamp = !!(_reset & BGFX_RESET_DEPTH_CLAMP); if (m_depthClamp != depthClamp) { @@ -2599,11 +2724,11 @@ WGPU_IMPORT if (!m_backBuffer.isSwapChain() ) { - if (m_resolution.width != _resolution.width - || m_resolution.height != _resolution.height) + if (m_mainSwapChain.width != _swapChain.width + || m_mainSwapChain.height != _swapChain.height) { - m_resolution.width = _resolution.width; - m_resolution.height = _resolution.height; + m_mainSwapChain.width = _swapChain.width; + m_mainSwapChain.height = _swapChain.height; for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) { @@ -2615,36 +2740,38 @@ WGPU_IMPORT return suspended; } - uint32_t flags = _resolution.reset & ~(0 + uint32_t flags = _reset & ~(0 | BGFX_RESET_SUSPEND | BGFX_RESET_MAXANISOTROPY | BGFX_RESET_DEPTH_CLAMP ); if (false - || m_resolution.formatColor != _resolution.formatColor - || m_resolution.formatDepthStencil != _resolution.formatDepthStencil - || m_resolution.width != _resolution.width - || m_resolution.height != _resolution.height - || m_resolution.reset != flags + || m_mainSwapChain.formatColor != _swapChain.formatColor + || m_mainSwapChain.formatDepthStencil != _swapChain.formatDepthStencil + || m_mainSwapChain.width != _swapChain.width + || m_mainSwapChain.height != _swapChain.height + || m_mainSwapChain.nwh != _swapChain.nwh + || m_mainSwapChain.ndt != _swapChain.ndt + || m_reset != flags ) { flags &= ~BGFX_RESET_INTERNAL_FORCE; - if (m_backBuffer.m_swapChain.m_nwh != g_platformData.nwh) + if (m_backBuffer.m_swapChain.m_nwh != m_mainSwapChain.nwh) { - m_backBuffer.m_swapChain.m_nwh = g_platformData.nwh; + m_backBuffer.m_swapChain.m_nwh = m_mainSwapChain.nwh; } - m_resolution = _resolution; - m_resolution.reset = flags; + m_mainSwapChain = _swapChain; + m_reset = flags; - m_textVideoMem.resize(false, _resolution.width, _resolution.height); + m_textVideoMem.resize(false, _swapChain.width, _swapChain.height); m_textVideoMem.clear(); preReset(); - m_backBuffer.update(m_resolution); + m_backBuffer.update(m_mainSwapChain); postReset(); } @@ -3209,10 +3336,7 @@ WGPU_IMPORT } } - const FrameBufferWGPU& fb = isValid(_fbh) - ? m_frameBuffers[_fbh.idx] - : m_backBuffer - ; + const FrameBufferWGPU& fb = getFrameBuffer(_fbh); murmur.add(layout.m_attributes, sizeof(layout.m_attributes) ); murmur.add(_msaaCount); @@ -3364,7 +3488,7 @@ WGPU_IMPORT ; const TextureFormat::Enum formatDepthStencil = fb.isSwapChain() - ? fb.m_swapChain.m_resolution.formatDepthStencil + ? fb.m_swapChain.m_desc.formatDepthStencil : TextureFormat::Enum(fb.m_formatDepthStencil) ; @@ -3692,7 +3816,7 @@ WGPU_IMPORT for (uint32_t ii = 0; ii < numAttachments; ++ii) { const WGPUTextureFormat format = isSwapChain - ? s_textureFormat[_fb.m_swapChain.m_resolution.formatColor].m_fmt + ? _fb.m_swapChain.m_viewFormat : m_textures[_fb.m_texture[ii].idx].m_fmt ; @@ -3731,8 +3855,9 @@ WGPU_IMPORT if (isSwapChain) { - _murmur.add(_fb.m_swapChain.m_resolution.formatColor); - _murmur.add(_fb.m_swapChain.m_resolution.formatDepthStencil); + _murmur.add(_fb.m_swapChain.m_viewFormat); + _murmur.add(_fb.m_swapChain.m_desc.formatColor); + _murmur.add(_fb.m_swapChain.m_desc.formatDepthStencil); return; } @@ -3811,7 +3936,8 @@ WGPU_IMPORT uint32_t m_maxFrameLatency; CommandQueueWGPU m_cmd; - Resolution m_resolution; + SwapChain m_mainSwapChain; + uint32_t m_reset; uint16_t m_maxAnisotropy; bool m_depthClamp; bool m_wireframe; @@ -5010,6 +5136,18 @@ WGPU_IMPORT { WGPUTextureFormat_RGBA8UnormSrgb, WGPUTextureFormat_BGRA8UnormSrgb }, }; + WGPUTextureFormat srgbFormat(WGPUTextureFormat _format) + { + switch (_format) + { + case WGPUTextureFormat_BGRA8Unorm: return WGPUTextureFormat_BGRA8UnormSrgb; + case WGPUTextureFormat_RGBA8Unorm: return WGPUTextureFormat_RGBA8UnormSrgb; + default: break; + } + + return _format; + } + WGPUTextureFormat findSurfaceCapsFormat(const WGPUSurfaceCapabilities& _surfaceCaps, WGPUTextureFormat _requestedFormat) { for (uint32_t ii = 0; ii < _surfaceCaps.formatCount; ++ii) @@ -5023,31 +5161,41 @@ WGPU_IMPORT return WGPUTextureFormat_Undefined; } - bool SwapChainWGPU::create(void* _nwh, const Resolution& _resolution) + bool SwapChainWGPU::create(void* _nwh, const SwapChain& _desc) { + m_desc = _desc; + if (NULL == _nwh || !createSurface(_nwh) ) { return false; } - return configure(_resolution); + return configure(_desc); } void SwapChainWGPU::destroy() { + wgpuRelease(m_textureView); + wgpuRelease(m_texture); + wgpuRelease(m_msaaTextureView); + wgpuRelease(m_depthStencilView); + WGPU_CHECK(wgpuSurfaceUnconfigure(m_surface) ); wgpuRelease(m_surface); - wgpuRelease(m_textureView); - wgpuRelease(m_depthStencilView); + + s_renderWGPU->m_cmd.kick(); + s_renderWGPU->m_cmd.wait(); + + wgpuInstanceProcessEvents(s_renderWGPU->m_instance); m_nwh = NULL; } - bool SwapChainWGPU::configure(const Resolution& _resolution) + bool SwapChainWGPU::configure(const SwapChain& _desc) { - m_resolution = _resolution; + m_desc = _desc; WGPUSurfaceCapabilities surfaceCaps = WGPU_SURFACE_CAPABILITIES_INIT; WGPUStatus status = WGPU_CHECK(wgpuSurfaceGetCapabilities(m_surface, s_renderWGPU->m_adapter, &surfaceCaps) ); @@ -5057,7 +5205,7 @@ WGPU_IMPORT return false; } - WGPUTextureFormat requestedFormat = s_textureFormat[m_resolution.formatColor].m_fmt; + WGPUTextureFormat requestedFormat = s_textureFormat[m_desc.formatColor].m_fmt; WGPUTextureFormat format = findSurfaceCapsFormat(surfaceCaps, requestedFormat); if (WGPUTextureFormat_Undefined == format) @@ -5067,7 +5215,7 @@ WGPU_IMPORT if (requestedFormat == s_swapChainFormatRemap[ii].requestedFormat) { format = findSurfaceCapsFormat(surfaceCaps, s_swapChainFormatRemap[ii].alternativeFormat); -m_resolution.formatColor = TextureFormat::BGRA8; + m_desc.formatColor = TextureFormat::BGRA8; break; } } @@ -5082,44 +5230,89 @@ m_resolution.formatColor = TextureFormat::BGRA8; if (WGPUTextureFormat_BGRA8Unorm == format) { - m_resolution.formatColor = TextureFormat::BGRA8; + m_desc.formatColor = TextureFormat::BGRA8; } else if (WGPUTextureFormat_RGBA8Unorm == format) { - m_resolution.formatColor = TextureFormat::RGBA8; + m_desc.formatColor = TextureFormat::RGBA8; } } #endif // BX_PLATFORM_EMSCRIPTEN BX_ASSERT(WGPUTextureFormat_Undefined != format, "SwapChain surface format is not available!"); + m_readable = 0 != (surfaceCaps.usages & WGPUTextureUsage_CopySrc); + + m_viewFormat = 0 != (m_desc.flags & BGFX_SWAP_CHAIN_SRGB_BACKBUFFER) + ? srgbFormat(format) + : format + ; + m_surfaceConfig = { .nextInChain = NULL, .device = s_renderWGPU->m_device, .format = format, - .usage = WGPUTextureUsage_RenderAttachment, - .width = m_resolution.width, - .height = m_resolution.height, - .viewFormatCount = 0, - .viewFormats = NULL, + .usage = WGPUTextureUsage_RenderAttachment + | (m_readable ? WGPUTextureUsage_CopySrc : 0) + , + .width = m_desc.width, + .height = m_desc.height, + .viewFormatCount = format != m_viewFormat ? 1ull : 0ull, + .viewFormats = format != m_viewFormat ? &m_viewFormat : NULL, .alphaMode = WGPUCompositeAlphaMode_Auto, .presentMode = WGPUPresentMode_Fifo, }; WGPU_CHECK(wgpuSurfaceConfigure(m_surface, &m_surfaceConfig) ); + wgpuRelease(m_textureView); + wgpuRelease(m_texture); + WGPUSurfaceTexture surfaceTexture = WGPU_SURFACE_TEXTURE_INIT; WGPU_CHECK(wgpuSurfaceGetCurrentTexture(m_surface, &surfaceTexture) ); - m_textureView = WGPU_CHECK(wgpuTextureCreateView(surfaceTexture.texture, NULL) ); - wgpuRelease(surfaceTexture.texture); - const uint32_t msaa = s_msaa[(_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT]; + if (NULL == surfaceTexture.texture) + { + BX_TRACE("Failed to acquire swap chain texture, status %d.", surfaceTexture.status); + return false; + } + + m_texture = surfaceTexture.texture; + m_textureView = createTextureView(); + + const uint32_t msaa = s_msaa[(_desc.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT]; wgpuRelease(m_depthStencilView); wgpuRelease(m_msaaTextureView); - if (bimg::isDepth(bimg::TextureFormat::Enum(m_resolution.formatDepthStencil) ) ) + if (isValid(m_desc.depth) ) + { + const TextureWGPU& texture = s_renderWGPU->m_textures[m_desc.depth.idx]; + + WGPUTexture depthTexture = 1 < msaa && NULL != texture.m_textureMsaa + ? texture.m_textureMsaa + : texture.m_texture + ; + + WGPUTextureViewDescriptor textureViewDesc = + { + .nextInChain = NULL, + .label = toWGPUStringView("SwapChain Shared Depth/Stencil"), + .format = texture.m_fmt, + .dimension = WGPUTextureViewDimension_2D, + .baseMipLevel = 0, + .mipLevelCount = 1, + .baseArrayLayer = 0, + .arrayLayerCount = 1, + .aspect = WGPUTextureAspect_All, + .usage = WGPUTextureUsage_RenderAttachment, + }; + + m_depthStencilView = WGPU_CHECK(wgpuTextureCreateView(depthTexture, &textureViewDesc) ); + m_formatDepthStencil = texture.m_textureFormat; + } + else if (bimg::isDepth(bimg::TextureFormat::Enum(m_desc.formatDepthStencil) ) ) { WGPUTextureDescriptor textureDesc = { @@ -5135,7 +5328,7 @@ m_resolution.formatColor = TextureFormat::BGRA8; .height = m_surfaceConfig.height, .depthOrArrayLayers = 1, }, - .format = s_textureFormat[m_resolution.formatDepthStencil].m_fmt, + .format = s_textureFormat[m_desc.formatDepthStencil].m_fmt, .mipLevelCount = 1, .sampleCount = msaa, .viewFormatCount = 0, @@ -5159,7 +5352,7 @@ m_resolution.formatColor = TextureFormat::BGRA8; }; m_depthStencilView = WGPU_CHECK(wgpuTextureCreateView(texture, &textureViewDesc) ); - m_formatDepthStencil = uint8_t(m_resolution.formatDepthStencil); + m_formatDepthStencil = uint8_t(m_desc.formatDepthStencil); wgpuRelease(texture); } @@ -5180,7 +5373,7 @@ m_resolution.formatColor = TextureFormat::BGRA8; .height = m_surfaceConfig.height, .depthOrArrayLayers = 1, }, - .format = format, + .format = m_viewFormat, .mipLevelCount = 1, .sampleCount = msaa, .viewFormatCount = 0, @@ -5210,14 +5403,14 @@ m_resolution.formatColor = TextureFormat::BGRA8; return true; } - void SwapChainWGPU::update(void* _nwh, const Resolution& _resolution) + void SwapChainWGPU::update(void* _nwh, const SwapChain& _desc) { BX_UNUSED(_nwh); wgpuRelease(m_textureView); wgpuRelease(m_msaaTextureView); wgpuRelease(m_depthStencilView); - configure(_resolution); + configure(_desc); } #if BX_PLATFORM_OSX || BX_PLATFORM_IOS || BX_PLATFORM_VISIONOS @@ -5342,7 +5535,7 @@ m_resolution.formatColor = TextureFormat::BGRA8; .next = NULL, .sType = WGPUSType_SurfaceSourceXlibWindow, }, - .display = g_platformData.ndt, + .display = m_desc.ndt, .window = uint64_t(m_nwh), }; @@ -5353,7 +5546,7 @@ m_resolution.formatColor = TextureFormat::BGRA8; .next = NULL, .sType = WGPUSType_SurfaceSourceWaylandSurface, }, - .display = g_platformData.ndt, + .display = m_desc.ndt, .surface = m_nwh, }; @@ -5410,9 +5603,29 @@ m_resolution.formatColor = TextureFormat::BGRA8; return NULL != m_surface; } + WGPUTextureView SwapChainWGPU::createTextureView() + { + WGPUTextureViewDescriptor textureViewDesc = + { + .nextInChain = NULL, + .label = toWGPUStringView("SwapChain Color"), + .format = m_viewFormat, + .dimension = WGPUTextureViewDimension_2D, + .baseMipLevel = 0, + .mipLevelCount = 1, + .baseArrayLayer = 0, + .arrayLayerCount = 1, + .aspect = WGPUTextureAspect_All, + .usage = m_surfaceConfig.usage, + }; + + return WGPU_CHECK(wgpuTextureCreateView(m_texture, &textureViewDesc) ); + } + void SwapChainWGPU::present() { wgpuRelease(m_textureView); + wgpuRelease(m_texture); #if !BX_PLATFORM_EMSCRIPTEN WGPU_CHECK(wgpuSurfacePresent(m_surface) ); #endif // !BX_PLATFORM_EMSCRIPTEN @@ -5440,8 +5653,12 @@ m_resolution.formatColor = TextureFormat::BGRA8; break; } - m_textureView = WGPU_CHECK(wgpuTextureCreateView(surfaceTexture.texture, NULL) ); - wgpuRelease(surfaceTexture.texture); + m_texture = surfaceTexture.texture; + + if (NULL != m_texture) + { + m_textureView = createTextureView(); + } } void FrameBufferWGPU::create(uint8_t _num, const Attachment* _attachment) @@ -5452,25 +5669,12 @@ m_resolution.formatColor = TextureFormat::BGRA8; postReset(); } - bool FrameBufferWGPU::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _colorFormat, TextureFormat::Enum _depthFormat) + bool FrameBufferWGPU::create(uint16_t _denseIdx, const SwapChain& _desc) { - bool result = true; + m_width = bx::max(_desc.width, 1); + m_height = bx::max(_desc.height, 1); - Resolution resolution = s_renderWGPU->m_resolution; - resolution.formatColor = TextureFormat::Count == _colorFormat ? resolution.formatColor : _colorFormat; - resolution.formatDepthStencil = TextureFormat::Count == _depthFormat ? resolution.formatDepthStencil : _depthFormat; - resolution.width = _width; - resolution.height = _height; - - m_width = bx::max(resolution.width, 1); - m_height = bx::max(resolution.height, 1); - - if (_denseIdx != UINT16_MAX) - { - resolution.reset &= ~BGFX_RESET_MSAA_MASK; - } - - result = m_swapChain.create(_nwh, resolution); + const bool result = m_swapChain.create(_desc.nwh, _desc); m_formatDepthStencil = m_swapChain.m_formatDepthStencil; m_denseIdx = _denseIdx; @@ -5573,11 +5777,11 @@ m_resolution.formatColor = TextureFormat::BGRA8; } } - void FrameBufferWGPU::update(const Resolution& _resolution) + void FrameBufferWGPU::update(const SwapChain& _desc) { - m_swapChain.update(m_swapChain.m_nwh, _resolution); - m_width = _resolution.width; - m_height = _resolution.height; + m_swapChain.update(m_swapChain.m_nwh, _desc); + m_width = _desc.width; + m_height = _desc.height; m_formatDepthStencil = m_swapChain.m_formatDepthStencil; } @@ -6528,7 +6732,7 @@ m_resolution.formatColor = TextureFormat::BGRA8; m_gpuTimer.readResultsAsync(); WGPU_CHECK(wgpuInstanceProcessEvents(s_renderWGPU->m_instance) ); - if (updateResolution(_render->m_resolution) ) + if (updateResolution(_render->m_mainSwapChain, _render->m_reset) ) { return; } @@ -6744,10 +6948,7 @@ m_resolution.formatColor = TextureFormat::BGRA8; profiler.begin(view); - FrameBufferWGPU& fb = isValid(fbh) - ? m_frameBuffers[fbh.idx] - : m_backBuffer - ; + FrameBufferWGPU& fb = getFrameBuffer(fbh); const bool isSwapChain = fb.isSwapChain(); @@ -7663,12 +7864,12 @@ m_resolution.formatColor = TextureFormat::BGRA8; , double(presentMax)*toMs ); - const uint32_t msaa = (m_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + const uint32_t msaa = (m_mainSwapChain.flags&BGFX_SWAP_CHAIN_MSAA_MASK)>>BGFX_SWAP_CHAIN_MSAA_SHIFT; tvm.printf(10, pos++, 0x8b, " Reset flags: [%c] vsync, [%c] MSAAx%d, [%c] MaxAnisotropy " - , !!(m_resolution.reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' + , !!(m_reset&BGFX_RESET_VSYNC) ? '\xfe' : ' ' , 0 != msaa ? '\xfe' : ' ' , 1<m_debugFrameBuffer, _render->m_debugTextScale); } else if (_render->m_debug & BGFX_DEBUG_TEXT) { - dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem); + dbgTextSubmit(this, _textVideoMemBlitter, _render->m_textVideoMem, _render->m_debugFrameBuffer, _render->m_debugTextScale); } m_presentElapsed = 0; diff --git a/src/renderer_webgpu.h b/src/renderer_webgpu.h index 8cf322a36..f581c17a2 100644 --- a/src/renderer_webgpu.h +++ b/src/renderer_webgpu.h @@ -671,31 +671,39 @@ namespace wgpu { SwapChainWGPU() : m_nwh(NULL) , m_surface(NULL) + , m_texture(NULL) , m_textureView(NULL) , m_msaaTextureView(NULL) , m_depthStencilView(NULL) + , m_viewFormat(WGPUTextureFormat_Undefined) + , m_readable(false) { } - bool create(void* _nwh, const Resolution& _resolution); + bool create(void* _nwh, const SwapChain& _desc); void destroy(); - void update(void* _nwh, const Resolution& _resolution); + void update(void* _nwh, const SwapChain& _desc); bool createSurface(void* _nwh); - bool configure(const Resolution& _resolution); + bool configure(const SwapChain& _desc); + WGPUTextureView createTextureView(); void present(); void* m_nwh; - Resolution m_resolution; + SwapChain m_desc; WGPUSurfaceConfiguration m_surfaceConfig; WGPUSurface m_surface; + WGPUTexture m_texture; WGPUTextureView m_textureView; WGPUTextureView m_msaaTextureView; WGPUTextureView m_depthStencilView; + WGPUTextureFormat m_viewFormat; + uint8_t m_formatDepthStencil; + bool m_readable; }; struct FrameBufferWGPU @@ -712,13 +720,13 @@ namespace wgpu { } void create(uint8_t _num, const Attachment* _attachment); - bool create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _colorFormat, TextureFormat::Enum _depthFormat = TextureFormat::Count); + bool create(uint16_t _denseIdx, const SwapChain& _desc); uint16_t destroy(); void preReset(); void postReset(); - void update(const Resolution& _resolution); + void update(const SwapChain& _desc); void present(); diff --git a/tools/geometryv/geometryv.cpp b/tools/geometryv/geometryv.cpp index cfb5bc456..544bc47e1 100644 --- a/tools/geometryv/geometryv.cpp +++ b/tools/geometryv/geometryv.cpp @@ -737,11 +737,11 @@ int _main_(int _argc, char** _argv) entry::setWindowSize(entry::kDefaultWindowHandle, view.m_width, view.m_height); bgfx::Init init; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); - init.resolution.width = view.m_width; - init.resolution.width = view.m_height; - init.resolution.reset = 0 + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); + init.swapChain.width = view.m_width; + init.swapChain.width = view.m_height; + init.reset = 0 | BGFX_RESET_VSYNC | BGFX_RESET_MSAA_X16 ; @@ -801,7 +801,7 @@ int _main_(int _argc, char** _argv) uint32_t fileIndex = 0; entry::WindowState windowState; - while (!entry::processWindowEvents(windowState, debug, init.resolution.reset) ) + while (!entry::processWindowEvents(windowState, debug, init.reset) ) { const entry::MouseState& mouseState = windowState.m_mouse; view.m_width = windowState.m_width; diff --git a/tools/texturev/texturev.cpp b/tools/texturev/texturev.cpp index e5d289782..c277af0fb 100644 --- a/tools/texturev/texturev.cpp +++ b/tools/texturev/texturev.cpp @@ -736,10 +736,16 @@ struct View else if (Output::HDR10 == m_outputFormat) { format = bgfx::TextureFormat::RGB10A2; - formatFlag = BGFX_RESET_HDR10; + formatFlag = BGFX_SWAP_CHAIN_HDR10; } - bgfx::reset(m_width, m_height, BGFX_RESET_VSYNC | formatFlag, format); + bgfx::SwapChain swapChain; + swapChain.width = m_width; + swapChain.height = m_height; + swapChain.flags = formatFlag; + swapChain.formatColor = format; + + bgfx::reset(BGFX_RESET_VSYNC, &swapChain); } } else if (0 == bx::strCmp(_argv[1], "help") ) @@ -1511,11 +1517,11 @@ int _main_(int _argc, char** _argv) : view.m_rendererType ; init.vendorId = args.m_pciId; - init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); - init.platformData.ndt = entry::getNativeDisplayHandle(); - init.resolution.width = view.m_width; - init.resolution.height = view.m_height; - init.resolution.reset = BGFX_RESET_VSYNC; + init.swapChain.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle); + init.swapChain.ndt = entry::getNativeDisplayHandle(); + init.swapChain.width = view.m_width; + init.swapChain.height = view.m_height; + init.reset = BGFX_RESET_VSYNC; init.videoDecode = true; bgfx::init(init); @@ -1662,7 +1668,7 @@ int _main_(int _argc, char** _argv) entry::WindowState windowState; entry::MouseState mouseStatePrev; - while (!entry::processWindowEvents(windowState, debug, init.resolution.reset) ) + while (!entry::processWindowEvents(windowState, debug, init.reset) ) { const entry::MouseState& mouseState = windowState.m_mouse; view.m_width = windowState.m_width;