diff --git a/Core/Graphics/InternalInclude/Babylon/Graphics/DeviceContext.h b/Core/Graphics/InternalInclude/Babylon/Graphics/DeviceContext.h index f0a9aeae2..7e3ac9393 100644 --- a/Core/Graphics/InternalInclude/Babylon/Graphics/DeviceContext.h +++ b/Core/Graphics/InternalInclude/Babylon/Graphics/DeviceContext.h @@ -121,6 +121,9 @@ namespace Babylon::Graphics TextureInfo GetTextureInfo(bgfx::TextureHandle handle); static bx::AllocatorI& GetDefaultAllocator() { return m_allocator; } + // call following method when a submit call is associated with the current acquired viewId + void InvalidateView(); + void Blit(bgfx::Encoder& encoder, bgfx::TextureHandle dst, uint16_t dstX, uint16_t dstY, bgfx::TextureHandle src, uint16_t srcX = 0, uint16_t srcY = 0, uint16_t width = UINT16_MAX, uint16_t height = UINT16_MAX); private: friend UpdateToken; @@ -130,5 +133,8 @@ namespace Babylon::Graphics std::mutex m_textureHandleToInfoMutex{}; static inline bx::DefaultAllocator m_allocator{}; + + bool m_currentViewIsUsed{false}; + bgfx::ViewId m_lastAcquiredViewId{bgfx::kInvalidHandle}; }; } diff --git a/Core/Graphics/InternalInclude/Babylon/Graphics/FrameBuffer.h b/Core/Graphics/InternalInclude/Babylon/Graphics/FrameBuffer.h index 6f9f4cda4..5e46a9a6c 100644 --- a/Core/Graphics/InternalInclude/Babylon/Graphics/FrameBuffer.h +++ b/Core/Graphics/InternalInclude/Babylon/Graphics/FrameBuffer.h @@ -41,7 +41,6 @@ namespace Babylon::Graphics void SetScissor(bgfx::Encoder& encoder, float x, float y, float width, float height); void Submit(bgfx::Encoder& encoder, bgfx::ProgramHandle programHandle, uint8_t flags); void SetStencil(bgfx::Encoder& encoder, uint32_t stencilState); - void Blit(bgfx::Encoder& encoder, bgfx::TextureHandle dst, uint16_t dstX, uint16_t dstY, bgfx::TextureHandle src, uint16_t srcX = 0, uint16_t srcY = 0, uint16_t width = UINT16_MAX, uint16_t height = UINT16_MAX); bool HasDepth() const { return m_hasDepth; } bool HasStencil() const { return m_hasStencil; } diff --git a/Core/Graphics/Source/DeviceContext.cpp b/Core/Graphics/Source/DeviceContext.cpp index 93512e0fd..2b29069c8 100644 --- a/Core/Graphics/Source/DeviceContext.cpp +++ b/Core/Graphics/Source/DeviceContext.cpp @@ -103,7 +103,9 @@ namespace Babylon::Graphics bgfx::ViewId DeviceContext::AcquireNewViewId(bgfx::Encoder& encoder) { - return m_graphicsImpl.AcquireNewViewId(encoder); + m_currentViewIsUsed = false; + m_lastAcquiredViewId = m_graphicsImpl.AcquireNewViewId(encoder); + return m_lastAcquiredViewId; } void DeviceContext::AddTexture(bgfx::TextureHandle handle, uint16_t width, uint16_t height, bool hasMips, uint16_t numLayers, bgfx::TextureFormat::Enum format) @@ -129,4 +131,22 @@ namespace Babylon::Graphics { return m_graphicsImpl.GetId(); } + + void DeviceContext::Blit(bgfx::Encoder& encoder, bgfx::TextureHandle dst, uint16_t dstX, uint16_t dstY, bgfx::TextureHandle src, uint16_t srcX, uint16_t srcY, uint16_t width, uint16_t height) + { + // Increment viewId so blit happens after the last drawcall of the last viewId if drawcall(s) have been submitted to the view. + // Otherwise, reuse last acquired viewId to not waste an Id. + auto viewId = m_lastAcquiredViewId; + if (!m_currentViewIsUsed) + { + viewId = AcquireNewViewId(encoder); + bgfx::touch(viewId); + } + encoder.blit(viewId, dst, dstX, dstY, src, srcX, srcY, width, height); + } + + void DeviceContext::InvalidateView() + { + m_currentViewIsUsed = true; + } } diff --git a/Core/Graphics/Source/FrameBuffer.cpp b/Core/Graphics/Source/FrameBuffer.cpp index c2d150f65..ee0ced2c9 100644 --- a/Core/Graphics/Source/FrameBuffer.cpp +++ b/Core/Graphics/Source/FrameBuffer.cpp @@ -112,6 +112,7 @@ namespace Babylon::Graphics m_bgfxScissor = {}; encoder.touch(m_viewId.value()); + m_deviceContext.InvalidateView(); } void FrameBuffer::SetViewPort(bgfx::Encoder& encoder, float x, float y, float width, float height) @@ -130,13 +131,7 @@ namespace Babylon::Graphics { SetBgfxViewPortAndScissor(encoder, m_desiredViewPort, m_desiredScissor); encoder.submit(m_viewId.value(), programHandle, 0, flags); - } - - void FrameBuffer::Blit(bgfx::Encoder& encoder, bgfx::TextureHandle dst, uint16_t dstX, uint16_t dstY, bgfx::TextureHandle src, uint16_t srcX, uint16_t srcY, uint16_t width, uint16_t height) - { - // In order for Blit to work properly we need to force the creation of a new ViewID. - SetBgfxViewPortAndScissor(encoder, m_desiredViewPort, m_desiredScissor); - encoder.blit(m_viewId.value(), dst, dstX, dstY, src, srcX, srcY, width, height); + m_deviceContext.InvalidateView(); } void FrameBuffer::SetStencil(bgfx::Encoder& encoder, uint32_t stencilState) diff --git a/Plugins/NativeEngine/Source/NativeEngine.cpp b/Plugins/NativeEngine/Source/NativeEngine.cpp index b342a0afb..4ea6f4799 100644 --- a/Plugins/NativeEngine/Source/NativeEngine.cpp +++ b/Plugins/NativeEngine/Source/NativeEngine.cpp @@ -1434,7 +1434,7 @@ namespace Babylon const auto textureSource = data.ReadPointer(); const auto textureDestination = data.ReadPointer(); - GetBoundFrameBuffer(*encoder).Blit(*encoder, textureDestination->Handle(), 0, 0, textureSource->Handle()); + m_deviceContext.Blit(*encoder, textureDestination->Handle(), 0, 0, textureSource->Handle()); } void NativeEngine::LoadRawTexture(const Napi::CallbackInfo& info)