From a44aaba1ce6afb80e992e4efaf0c86df57b17b74 Mon Sep 17 00:00:00 2001 From: "matthieu.begoghina" <12561988+Voulz@users.noreply.github.com> Date: Sat, 23 Mar 2024 23:20:35 +1100 Subject: [PATCH 1/5] Initial fix for DX11 Blend, Rasterizer and DepthStencil states --- .../Platform/RiveRenderTargetD3D11.cpp | 100 ++++++++++++++-- .../Private/Platform/RiveRenderTargetD3D11.h | 19 +-- .../Private/Platform/RiveRendererD3D11.cpp | 108 +++++++++++------- .../Private/Platform/RiveRendererD3D11.h | 14 ++- .../RiveRenderer/Private/RiveRenderTarget.cpp | 14 +-- .../RiveRenderer/Private/RiveRenderTarget.h | 6 +- 6 files changed, 183 insertions(+), 78 deletions(-) diff --git a/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp b/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp index 6da77710..c737ffea 100644 --- a/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp +++ b/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp @@ -3,6 +3,11 @@ #include "RiveRenderTargetD3D11.h" #if PLATFORM_WINDOWS +#include "CommonRenderResources.h" +#include "RenderGraphBuilder.h" +#include "ScreenRendering.h" +#include "Engine/Texture2DDynamic.h" + #include "RiveRendererD3D11.h" #include "ID3D11DynamicRHI.h" #include "Logs/RiveRendererLog.h" @@ -63,22 +68,103 @@ void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::CacheTextureTarget_Ren } } +void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::Render_RenderThread(FRHICommandListImmediate& RHICmdList, const TArray& RiveRenderCommands) +{ + // ID3D11DynamicRHI* D3D11RHI = GetID3D11DynamicRHI(); + // ID3D11Device* D3D11DevicePtr = D3D11RHI->RHIGetDevice(); + // ID3D11DeviceContext* D3D11DeviceContext = nullptr; + // D3D11DevicePtr->GetImmediateContext(&D3D11DeviceContext); + + // FRDGBuilder GraphBuilder(RHICmdList); + + // -- First, we start a render pass todo: might not be needed + FTextureRHIRef TargetTexture = RenderTarget->GetResource()->TextureRHI; + RHICmdList.Transition(FRHITransitionInfo(TargetTexture, ERHIAccess::Unknown, ERHIAccess::RTV)); + FRHIRenderPassInfo RPInfo(TargetTexture, ERenderTargetActions::Load_Store); + RHICmdList.BeginRenderPass(RPInfo, TEXT("RiveRenderingTexture")); + // { + // FGlobalShaderMap* ShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel); + // TShaderMapRef VertexShader(ShaderMap); + // TShaderMapRef PixelShader(ShaderMap); + // + // FGraphicsPipelineStateInitializer GraphicsPSOInit; + // RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit); + // GraphicsPSOInit.BlendState = TStaticBlendState::GetRHI(); + // GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI(); + // GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState::GetRHI(); + // GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI; + // GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader(); + // GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader(); + // GraphicsPSOInit.PrimitiveType = PT_TriangleList; + // + // SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0); + // SetShaderParametersLegacyPS(RHICmdList, PixelShader, TStaticSamplerState::GetRHI(), TargetTexture); + // } + // RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread); + + + // -- Then we render Rive, ensuring the DX11 states are reset before the call + RHICmdList.EnqueueLambda([this, RiveRenderCommands](FRHICommandListImmediate& RHICmdList) + { + RiveRendererD3D11->ResetDXStateForRive(); + FRiveRenderTarget::Render_Internal(RiveRenderCommands, &RHICmdList); + RiveRendererD3D11->ResetDXState(); + }); + // RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread); + + + // ID3D11DynamicRHI* D3D11RHI = GetID3D11DynamicRHI(); + // if (IRHICommandContextPSOFallback* PsoFallback = (IRHICommandContextPSOFallback*)D3D11RHI) + // { + // PsoFallback->RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); + // PsoFallback->RHISetBlendState(TStaticBlendState::GetRHI(), FLinearColor(1.0f, 1.0f, 1.0f)); + // PsoFallback->RHISetDepthStencilState(TStaticDepthStencilState<>::GetRHI(), 0); + // } + + // -- Lastly, now that we have manually reset DX11, we need to update the state to ensure it matches the direct calls we just made + { + FGlobalShaderMap* ShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel); + TShaderMapRef VertexShader(ShaderMap); // just a default todo: might need to be forced set + TShaderMapRef PixelShader(ShaderMap); // just a default todo: might need to be forced set + + FGraphicsPipelineStateInitializer GraphicsPSOInit; + RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit); + // same as default D3D11_BLEND_DESC which is same as passing null to OMSetBlendState + GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI(); + // NOT the same as default D3D11_RASTERIZER_DESC, a matching Rasterizer has been created in FRiveRendererD3D11GPUAdapter::InitBlendState + GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI(); + // NOT the same as default D3D11_DEPTH_STENCIL_DESC, a matching DepthStencil has been created in FRiveRendererD3D11GPUAdapter::InitBlendState + GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState::GetRHI(); + GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI; // just a default todo: might need to be forced set + GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader(); + GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader(); + GraphicsPSOInit.PrimitiveType = PT_TriangleList; // just a default todo: might need to be forced set + SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0, EApplyRendertargetOption::CheckApply, false); + } + RHICmdList.EndRenderPass(); + RHICmdList.Transition(FRHITransitionInfo(TargetTexture, ERHIAccess::RTV, ERHIAccess::SRVMask)); + // RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread); + + // GraphBuilder.Execute(); +} + rive::rcp UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::GetRenderTarget() const { return CachedPLSRenderTargetD3D; } -#if WITH_RIVE -void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::EndFrame() const +std::unique_ptr UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::BeginFrame(FRHICommandListImmediate* RHICmdListPtr) { - FRiveRenderTarget::EndFrame(); - ResetBlendState(); + check(RHICmdListPtr); + check(RenderTarget->GetResource()->TextureRHI); + + return FRiveRenderTarget::BeginFrame(RHICmdListPtr); } -void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::ResetBlendState() const +#if WITH_RIVE +void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::EndFrame(FRHICommandListImmediate* RHICmdListPtr) const { - check(IsInRenderingThread()); - RiveRendererD3D11->ResetBlendState(); + FRiveRenderTarget::EndFrame(RHICmdListPtr); } #endif // WITH_RIVE diff --git a/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.h b/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.h index a3f4ed72..f806c694 100644 --- a/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.h +++ b/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.h @@ -32,36 +32,29 @@ namespace UE::Rive::Renderer::Private FRiveRenderTargetD3D11(const TSharedRef& InRiveRenderer, const FName& InRiveName, UTexture2DDynamic* InRenderTarget); virtual ~FRiveRenderTargetD3D11() override; + //~ BEGIN : IRiveRenderTarget Interface - public: virtual void CacheTextureTarget_RenderThread(FRHICommandListImmediate& RHICmdList, const FTexture2DRHIRef& InRHIResource) override; - -#if WITH_RIVE - //~ END : IRiveRenderTarget Interface - + +#if WITH_RIVE //~ BEGIN : FRiveRenderTarget Interface - protected: // It Might need to be on rendering thread, render QUEUE is required + virtual void Render_RenderThread(FRHICommandListImmediate& RHICmdList, const TArray& RiveRenderCommands) override; virtual rive::rcp GetRenderTarget() const override; - virtual void EndFrame() const override; + virtual std::unique_ptr BeginFrame(FRHICommandListImmediate* RHICmdList) override; + virtual void EndFrame(FRHICommandListImmediate* RHICmdList) const override; //~ END : FRiveRenderTarget Interface /** * Attribute(s) */ - - private: - void ResetBlendState() const; - private: TSharedRef RiveRendererD3D11; - rive::rcp CachedPLSRenderTargetD3D; - #endif // WITH_RIVE }; } diff --git a/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp b/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp index 7f522b3a..fc47e96b 100644 --- a/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp +++ b/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp @@ -6,6 +6,7 @@ #include "ID3D11DynamicRHI.h" #include "Logs/RiveRendererLog.h" #include "ProfilingDebugging/RealtimeGPUProfiler.h" +#include "D3D11State.h" #include "RiveRenderTargetD3D11.h" #include "Windows/D3D11ThirdParty.h" @@ -28,18 +29,16 @@ void UE::Rive::Renderer::Private::FRiveRendererD3D11GPUAdapter::Initialize(rive: D3D11DeviceContext = nullptr; D3D11DevicePtr->GetImmediateContext(&D3D11DeviceContext); - if (SUCCEEDED(D3D11DevicePtr->QueryInterface(__uuidof(IDXGIDevice), (void**)&DXGIDevice))) + if (SUCCEEDED(D3D11DevicePtr->QueryInterface(__uuidof(IDXGIDevice), (void**)DXGIDevice.GetInitReference()))) { - IDXGIAdapter* DXGIAdapter; - if (SUCCEEDED(DXGIDevice->GetAdapter(&DXGIAdapter))) + TRefCountPtr DXGIAdapter; + if (SUCCEEDED(DXGIDevice->GetAdapter(DXGIAdapter.GetInitReference()))) { DXGI_ADAPTER_DESC AdapterDesc; DXGIAdapter->GetDesc(&AdapterDesc); OutContextOptions.isIntel = AdapterDesc.VendorId == 0x163C || AdapterDesc.VendorId == 0x8086 || AdapterDesc.VendorId == 0x8087; - - DXGIAdapter->Release(); } } @@ -48,65 +47,82 @@ void UE::Rive::Renderer::Private::FRiveRendererD3D11GPUAdapter::Initialize(rive: } #endif // WITH_RIVE -void UE::Rive::Renderer::Private::FRiveRendererD3D11GPUAdapter::ResetBlendState() +void UE::Rive::Renderer::Private::FRiveRendererD3D11GPUAdapter::ResetDXStateForRive() { if (!D3D11DeviceContext) { - UE_LOG(LogRiveRenderer, Warning, TEXT("D3D11DeviceContext is nullptr while resetting of blend state")); + UE_LOG(LogRiveRenderer, Warning, TEXT("D3D11DeviceContext is nullptr while resetting the DirectX state")); return; } - // Reference is here FSlateD3D11RenderingPolicy::DrawElements(), set the blend state back to whatever Unreal expects after Rive renderers - D3D11DeviceContext->OMSetBlendState( AlphaBlendState, nullptr, 0xFFFFFFFF ); + // Rive is resetting the Rasterizer and BlendState in PLSRenderContextD3DImpl::flush, so no need to call them + // the DepthStencil is not set by Rive, so we reset to default + D3D11DeviceContext->OMSetDepthStencilState(nullptr, 0); +} - // Reset the Raster state when finished, there are places that are making assumptions about the raster state - // that need to be fixed. - D3D11DeviceContext->RSSetState(NormalRasterState); +void UE::Rive::Renderer::Private::FRiveRendererD3D11GPUAdapter::ResetDXState() +{ + if (!D3D11DeviceContext) + { + UE_LOG(LogRiveRenderer, Warning, TEXT("D3D11DeviceContext is nullptr while resetting the DirectX state")); + return; + } + + // We don't need to set a BlendState because we can match the default with TStaticBlendState<>::GetRHI(); + D3D11DeviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF); + // We need a Rasterizer because the default state sets D3D11_RASTERIZER_DESC::FrontCounterClockwise to false, but UE sets it to true + D3D11DeviceContext->RSSetState(DefaultRasterState); + // We also need a DepthStencil because the default raster state states D3D11_DEPTH_STENCIL_DESC::DepthWriteMask to D3D11_DEPTH_WRITE_MASK_ALL, but UE crashed with that option + D3D11DeviceContext->OMSetDepthStencilState(DefaultDepthStencilState, 0); } void UE::Rive::Renderer::Private::FRiveRendererD3D11GPUAdapter::InitBlendState() { check(IsInRenderingThread()); check(D3D11DevicePtr); - - D3D11_BLEND_DESC BlendDesc; - BlendDesc.AlphaToCoverageEnable = false; - BlendDesc.IndependentBlendEnable = false; - BlendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; - BlendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; - - // dest.a = 1-(1-dest.a)*src.a + dest.a - BlendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; - BlendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE; - BlendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; - - BlendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; - BlendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - BlendDesc.RenderTarget[0].BlendEnable = true; - - HRESULT Hr = D3D11DevicePtr->CreateBlendState( &BlendDesc, AlphaBlendState.GetInitReference() ); - if (FAILED(Hr)) - { - UE_LOG(LogRiveRenderer, Warning, TEXT("D3D11DevicePtr->CreateBlendState( &BlendDesc, AlphaBlendState.GetInitReference() ) Failed")); - return; - } + // Below is matching TStaticRasterizerState<>::GetRHI(); D3D11_RASTERIZER_DESC RasterDesc; + FMemory::Memzero(&RasterDesc,sizeof(D3D11_RASTERIZER_DESC)); RasterDesc.CullMode = D3D11_CULL_NONE; RasterDesc.FillMode = D3D11_FILL_SOLID; + RasterDesc.SlopeScaledDepthBias = 0.f; RasterDesc.FrontCounterClockwise = true; - RasterDesc.DepthBias = 0; - RasterDesc.DepthBiasClamp = 0; - RasterDesc.SlopeScaledDepthBias = 0; - RasterDesc.ScissorEnable = false; - RasterDesc.MultisampleEnable = false; + RasterDesc.DepthBias = 0.f; + RasterDesc.DepthClipEnable = true; + RasterDesc.MultisampleEnable = true; + RasterDesc.ScissorEnable = true; + RasterDesc.AntialiasedLineEnable = false; + RasterDesc.DepthBiasClamp = 0.f; - Hr = D3D11DevicePtr->CreateRasterizerState( &RasterDesc, NormalRasterState.GetInitReference() ); + HRESULT Hr = D3D11DevicePtr->CreateRasterizerState(&RasterDesc, DefaultRasterState.GetInitReference()); if (FAILED(Hr)) { UE_LOG(LogRiveRenderer, Warning, TEXT("D3D11DevicePtr->CreateRasterizerState( &RasterDesc, NormalRasterState.GetInitReference() ) Failed")); } + + // Below is matching TStaticDepthStencilState::GetRHI(); + D3D11_DEPTH_STENCIL_DESC DepthStencilDesc; + FMemory::Memzero(&DepthStencilDesc,sizeof(D3D11_DEPTH_STENCIL_DESC)); + DepthStencilDesc.DepthEnable = true; // because DepthTest = CF_DepthNearOrEqual + DepthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; + DepthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; // CF_DepthNearOrEqual has no match + + DepthStencilDesc.StencilEnable = false; + DepthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS ; + DepthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + DepthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + DepthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + DepthStencilDesc.BackFace = DepthStencilDesc.FrontFace; + DepthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + DepthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + + Hr = D3D11DevicePtr->CreateDepthStencilState( &DepthStencilDesc, DefaultDepthStencilState.GetInitReference() ); + if (FAILED(Hr)) + { + UE_LOG(LogRiveRenderer, Warning, TEXT("D3D11DevicePtr->CreateDepthStencilState( &DepthStencilDesc, DepthStencilState.GetInitReference() ) Failed")); + } } // ------------- FRiveRendererD3D11 ------------- @@ -152,14 +168,22 @@ void UE::Rive::Renderer::Private::FRiveRendererD3D11::CreatePLSRenderer_RenderTh RIVE_DEBUG_FUNCTION_INDENT; } -void UE::Rive::Renderer::Private::FRiveRendererD3D11::ResetBlendState() const +void UE::Rive::Renderer::Private::FRiveRendererD3D11::ResetDXStateForRive() const { check(IsInRenderingThread()); check(D3D11GPUAdapter.IsValid()); FScopeLock Lock(&ThreadDataCS); + D3D11GPUAdapter->ResetDXStateForRive(); +} - D3D11GPUAdapter->ResetBlendState(); +void UE::Rive::Renderer::Private::FRiveRendererD3D11::ResetDXState() const +{ + check(IsInRenderingThread()); + check(D3D11GPUAdapter.IsValid()); + + FScopeLock Lock(&ThreadDataCS); + D3D11GPUAdapter->ResetDXState(); } #endif // PLATFORM_WINDOWS diff --git a/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.h b/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.h index 7b85d039..7070a0fc 100644 --- a/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.h +++ b/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.h @@ -35,7 +35,8 @@ namespace UE::Rive::Renderer::Private #if WITH_RIVE void Initialize(rive::pls::PLSRenderContextD3DImpl::ContextOptions& OutContextOptions); #endif // WITH_RIVE - void ResetBlendState(); + void ResetDXStateForRive(); + void ResetDXState(); ID3D11DynamicRHI* GetD3D11RHI() const { return D3D11RHI; } ID3D11Device* GetD3D11DevicePtr() const { return D3D11DevicePtr; } @@ -48,10 +49,10 @@ namespace UE::Rive::Renderer::Private ID3D11DynamicRHI* D3D11RHI = nullptr; ID3D11Device* D3D11DevicePtr = nullptr; ID3D11DeviceContext* D3D11DeviceContext = nullptr; - IDXGIDevice* DXGIDevice = nullptr; - - TRefCountPtr AlphaBlendState; - TRefCountPtr NormalRasterState; + TRefCountPtr DXGIDevice = nullptr; + + TRefCountPtr DefaultDepthStencilState; + TRefCountPtr DefaultRasterState; }; class RIVERENDERER_API FRiveRendererD3D11 : public FRiveRenderer @@ -73,7 +74,8 @@ namespace UE::Rive::Renderer::Private //~ END : IRiveRenderer Interface - void ResetBlendState() const; + void ResetDXStateForRive() const; + void ResetDXState() const; private: TUniquePtr D3D11GPUAdapter; diff --git a/Source/RiveRenderer/Private/RiveRenderTarget.cpp b/Source/RiveRenderer/Private/RiveRenderTarget.cpp index 2617e83e..f05cd8fb 100644 --- a/Source/RiveRenderer/Private/RiveRenderTarget.cpp +++ b/Source/RiveRenderer/Private/RiveRenderTarget.cpp @@ -152,7 +152,7 @@ FMatrix UE::Rive::Renderer::Private::FRiveRenderTarget::GetTransformMatrix() con return CurrentMatrix; } -std::unique_ptr UE::Rive::Renderer::Private::FRiveRenderTarget::BeginFrame() +std::unique_ptr UE::Rive::Renderer::Private::FRiveRenderTarget::BeginFrame(FRHICommandListImmediate* RHICmdListPtr) { rive::pls::PLSRenderContext* PLSRenderContextPtr = RiveRenderer->GetPLSRenderContextPtr(); if (PLSRenderContextPtr == nullptr) @@ -182,7 +182,7 @@ std::unique_ptr UE::Rive::Renderer::Private::FRiveRender return std::make_unique(PLSRenderContextPtr); } -void UE::Rive::Renderer::Private::FRiveRenderTarget::EndFrame() const +void UE::Rive::Renderer::Private::FRiveRenderTarget::EndFrame(FRHICommandListImmediate* RHICmdListPtr) const { rive::pls::PLSRenderContext* PLSRenderContextPtr = RiveRenderer->GetPLSRenderContextPtr(); if (PLSRenderContextPtr == nullptr) @@ -214,11 +214,11 @@ void UE::Rive::Renderer::Private::FRiveRenderTarget::Render_RenderThread(FRHICom { SCOPED_GPU_STAT(RHICmdList, Render); check(IsInRenderingThread()); - - Render_Internal(RiveRenderCommands); + + Render_Internal(RiveRenderCommands, &RHICmdList); } -void UE::Rive::Renderer::Private::FRiveRenderTarget::Render_Internal(const TArray& RiveRenderCommands) +void UE::Rive::Renderer::Private::FRiveRenderTarget::Render_Internal(const TArray& RiveRenderCommands, FRHICommandListImmediate* RHICmdListPtr) { FScopeLock Lock(&RiveRenderer->GetThreadDataCS()); @@ -234,7 +234,7 @@ void UE::Rive::Renderer::Private::FRiveRenderTarget::Render_Internal(const TArra #endif // Begin Frame - std::unique_ptr PLSRenderer = BeginFrame(); + std::unique_ptr PLSRenderer = BeginFrame(RHICmdListPtr); if (PLSRenderer == nullptr) { return; @@ -276,5 +276,5 @@ void UE::Rive::Renderer::Private::FRiveRenderTarget::Render_Internal(const TArra } } - EndFrame(); + EndFrame(RHICmdListPtr); } diff --git a/Source/RiveRenderer/Private/RiveRenderTarget.h b/Source/RiveRenderer/Private/RiveRenderTarget.h index e3a615f2..c22b1cae 100644 --- a/Source/RiveRenderer/Private/RiveRenderTarget.h +++ b/Source/RiveRenderer/Private/RiveRenderTarget.h @@ -60,10 +60,10 @@ namespace UE::Rive::Renderer::Private protected: virtual rive::rcp GetRenderTarget() const = 0; - virtual std::unique_ptr BeginFrame(); - virtual void EndFrame() const; + virtual std::unique_ptr BeginFrame(FRHICommandListImmediate* RHICmdListPtr); + virtual void EndFrame(FRHICommandListImmediate* RHICmdListPtr) const; virtual void Render_RenderThread(FRHICommandListImmediate& RHICmdList, const TArray& RiveRenderCommands); - virtual void Render_Internal(const TArray& RiveRenderCommands); + virtual void Render_Internal(const TArray& RiveRenderCommands, FRHICommandListImmediate* RHICmdListPtr); #endif // WITH_RIVE protected: From 6f7e54126c9a778234683831118fd1383a1a1896 Mon Sep 17 00:00:00 2001 From: "matthieu.begoghina" <12561988+Voulz@users.noreply.github.com> Date: Mon, 25 Mar 2024 18:38:16 +1100 Subject: [PATCH 2/5] Fix for RiveActor to handle change of Artboards --- Source/Rive/Private/Game/RiveActor.cpp | 2 +- Source/Rive/Private/Rive/RiveFile.cpp | 2 + Source/Rive/Private/Slate/SRiveWidget.cpp | 57 +++++++++++++++++++++-- Source/Rive/Public/Rive/RiveFile.h | 6 ++- Source/Rive/Public/Slate/SRiveWidget.h | 3 ++ 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/Source/Rive/Private/Game/RiveActor.cpp b/Source/Rive/Private/Game/RiveActor.cpp index d6e089a0..8f0ad53b 100644 --- a/Source/Rive/Private/Game/RiveActor.cpp +++ b/Source/Rive/Private/Game/RiveActor.cpp @@ -119,7 +119,7 @@ void ARiveActor::EndPlay(const EEndPlayReason::Type EndPlayReason) } } - if (EndPlayReason == EEndPlayReason::EndPlayInEditor) + if (EndPlayReason == EEndPlayReason::EndPlayInEditor && IsValid(RiveFile)) { RiveFile->InstantiateArtboard(); } diff --git a/Source/Rive/Private/Rive/RiveFile.cpp b/Source/Rive/Private/Rive/RiveFile.cpp index b8d27242..5ae16078 100644 --- a/Source/Rive/Private/Rive/RiveFile.cpp +++ b/Source/Rive/Private/Rive/RiveFile.cpp @@ -433,6 +433,7 @@ void URiveFile::Initialize() UE_LOG(LogRive, Error, TEXT("Failed to instantiate the Artboard after importing the rive file.")); BroadcastInitializationResult(false); } + OnArtboardChangedRaw.Broadcast(this, Artboard); OnArtboardChanged.Broadcast(this, Artboard); // Now we can broadcast the Artboard Changed Event return; } @@ -528,6 +529,7 @@ void URiveFile::InstantiateArtboard(bool bRaiseArtboardChangedEvent) if (bRaiseArtboardChangedEvent) { + OnArtboardChangedRaw.Broadcast(this, Artboard); OnArtboardChanged.Broadcast(this, Artboard); } } diff --git a/Source/Rive/Private/Slate/SRiveWidget.cpp b/Source/Rive/Private/Slate/SRiveWidget.cpp index 4d2ae1a2..dc65d7ef 100644 --- a/Source/Rive/Private/Slate/SRiveWidget.cpp +++ b/Source/Rive/Private/Slate/SRiveWidget.cpp @@ -4,6 +4,14 @@ #include "RiveWidgetView.h" #include "Rive/RiveFile.h" +SRiveWidget::~SRiveWidget() +{ + if (IsValid(RiveFile)) + { + RiveFile->OnArtboardChangedRaw.Remove(OnArtboardChangedHandle); + } +} + void SRiveWidget::Construct(const FArguments& InArgs) { ChildSlot @@ -38,9 +46,52 @@ void SRiveWidget::RegisterArtboardInputs(const TArray& InArtboar void SRiveWidget::SetRiveFile(URiveFile* InRiveFile) { - if (RiveWidgetView && IsValid(InRiveFile)) + if (!RiveWidgetView || InRiveFile == RiveFile) + { + return; + } + + if (IsValid(RiveFile)) + { + RiveFile->OnArtboardChangedRaw.Remove(OnArtboardChangedHandle); + } + + if (IsValid(InRiveFile)) + { + RiveFile = InRiveFile; + RiveWidgetView->SetRiveTexture(RiveFile); + if (URiveArtboard* Artboard = RiveFile->GetArtboard()) + { + RiveWidgetView->RegisterArtboardInputs({ Artboard }); + } + else + { + RiveWidgetView->RegisterArtboardInputs({}); + } + + TWeakPtr WeakRiveWidget = SharedThis(this).ToWeakPtr(); + OnArtboardChangedHandle = InRiveFile->OnArtboardChangedRaw.AddSPLambda(this, [WeakRiveWidget, InRiveFile](URiveFile* File, URiveArtboard* Artboard) + { + if (const TSharedPtr RiveWidget = WeakRiveWidget.Pin()) + { + if (ensure(InRiveFile == File) && RiveWidget->RiveWidgetView) + { + if (Artboard) + { + RiveWidget->RiveWidgetView->RegisterArtboardInputs({ Artboard }); + } + else + { + RiveWidget->RiveWidgetView->RegisterArtboardInputs({}); + } + } + } + }); + } + else { - RiveWidgetView->SetRiveTexture(InRiveFile); - RiveWidgetView->RegisterArtboardInputs({ InRiveFile->GetArtboard() }); + RiveFile = nullptr; + RiveWidgetView->SetRiveTexture(RiveFile); + RiveWidgetView->RegisterArtboardInputs({}); } } diff --git a/Source/Rive/Public/Rive/RiveFile.h b/Source/Rive/Public/Rive/RiveFile.h index d69fba83..bb32bc1c 100644 --- a/Source/Rive/Public/Rive/RiveFile.h +++ b/Source/Rive/Public/Rive/RiveFile.h @@ -34,7 +34,8 @@ class RIVE_API URiveFile : public URiveTexture, public FTickableGameObject GENERATED_BODY() public: - DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnArtboardChanged, URiveFile*, RiveFile, URiveArtboard*, Artboard); + DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnArtboardChangedDynamic, URiveFile*, RiveFile, URiveArtboard*, Artboard); + DECLARE_MULTICAST_DELEGATE_TwoParams(FOnArtboardChanged, URiveFile* /* RiveFile */, URiveArtboard* /* Artboard */); DECLARE_MULTICAST_DELEGATE_TwoParams(FOnRiveFileInitialized, URiveFile*, bool /* bSuccess */ ); DECLARE_MULTICAST_DELEGATE_OneParam(FOnRiveFileEvent, URiveFile*); DECLARE_DYNAMIC_MULTICAST_DELEGATE(FRiveReadyDelegate); @@ -162,7 +163,8 @@ class RIVE_API URiveFile : public URiveTexture, public FTickableGameObject public: UPROPERTY(BlueprintAssignable, Category = Rive) - FOnArtboardChanged OnArtboardChanged; + FOnArtboardChangedDynamic OnArtboardChanged; + FOnArtboardChanged OnArtboardChangedRaw; UPROPERTY() TArray RiveFileData; diff --git a/Source/Rive/Public/Slate/SRiveWidget.h b/Source/Rive/Public/Slate/SRiveWidget.h index 0d339201..0e15f362 100644 --- a/Source/Rive/Public/Slate/SRiveWidget.h +++ b/Source/Rive/Public/Slate/SRiveWidget.h @@ -27,6 +27,7 @@ class RIVE_API SRiveWidget : public SCompoundWidget #endif SLATE_END_ARGS() + ~SRiveWidget() override; /** * Implementation(s) */ @@ -48,4 +49,6 @@ class RIVE_API SRiveWidget : public SCompoundWidget /** Reference to Avalanche View */ TSharedPtr RiveWidgetView; + URiveFile* RiveFile = nullptr; + FDelegateHandle OnArtboardChangedHandle; }; From 68977937c2b62df3f73ee5975fd41aed660c3e3e Mon Sep 17 00:00:00 2001 From: "matthieu.begoghina" <12561988+Voulz@users.noreply.github.com> Date: Mon, 25 Mar 2024 19:37:06 +1100 Subject: [PATCH 3/5] UR-146: Added the menu entry Create Rive Widget --- .../RiveFile_AssetDefinitionDefault.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Source/RiveEditor/Private/RiveFile_AssetDefinitionDefault.cpp b/Source/RiveEditor/Private/RiveFile_AssetDefinitionDefault.cpp index 29336e39..e70e92be 100644 --- a/Source/RiveEditor/Private/RiveFile_AssetDefinitionDefault.cpp +++ b/Source/RiveEditor/Private/RiveFile_AssetDefinitionDefault.cpp @@ -6,6 +6,7 @@ #include "IAssetTools.h" #include "RiveAssetToolkit.h" #include "Factories/RiveFileInstanceFactory.h" +#include "Factories/RiveWidgetFactory.h" #include "Logs/RiveEditorLog.h" #include "Rive/RiveFile.h" @@ -28,6 +29,19 @@ namespace MenuExtension_RiveFile }); } + void ExecuteCreateWidget(const FToolMenuContext& InContext) + { + const UContentBrowserAssetContextMenuContext* CBContext = UContentBrowserAssetContextMenuContext::FindContextWithAssets(InContext); + + TArray RiveFiles = CBContext->LoadSelectedObjects(); + for (URiveFile* RiveFile : RiveFiles) + { + if (IsValid(RiveFile)) + { + FRiveWidgetFactory(RiveFile).Create(); + } + } + } static FDelayedAutoRegisterHelper DelayedAutoRegister(EDelayedRegisterRunPhase::EndOfEngineInit, []{ UToolMenus::RegisterStartupCallback(FSimpleMulticastDelegate::FDelegate::CreateLambda([]() @@ -47,6 +61,13 @@ namespace MenuExtension_RiveFile const FToolMenuExecuteAction UIAction = FToolMenuExecuteAction::CreateStatic(&ExecuteCreateInstance); InSection.AddMenuEntry("RiveFile_CreateInstance", Label, ToolTip, Icon, UIAction); } + { + const TAttribute Label = LOCTEXT("RiveFile_CreateWidget", "Create Rive Widget"); + const TAttribute ToolTip = LOCTEXT("RiveFile_CreateWidgetTooltip", "Creates a new Rive Widget asset using this file."); + const FSlateIcon Icon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "ClassIcon.WidgetBlueprint"); + const FToolMenuExecuteAction UIAction = FToolMenuExecuteAction::CreateStatic(&ExecuteCreateWidget); + InSection.AddMenuEntry("RiveFile_CreateWidget", Label, ToolTip, Icon, UIAction); + } } })); })); From 20f1f933494e7c73834fc8b7008041053e8010a8 Mon Sep 17 00:00:00 2001 From: "matthieu.begoghina" <12561988+Voulz@users.noreply.github.com> Date: Mon, 25 Mar 2024 20:27:02 +1100 Subject: [PATCH 4/5] Code clean for DX11 fix --- .../Platform/RiveRenderTargetD3D11.cpp | 69 ++----------------- .../Private/Platform/RiveRenderTargetD3D11.h | 3 - .../Private/Platform/RiveRendererD3D11.cpp | 1 - .../RiveRenderer/Private/RiveRenderTarget.cpp | 12 ++-- .../RiveRenderer/Private/RiveRenderTarget.h | 6 +- 5 files changed, 16 insertions(+), 75 deletions(-) diff --git a/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp b/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp index c737ffea..e595195f 100644 --- a/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp +++ b/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp @@ -70,62 +70,25 @@ void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::CacheTextureTarget_Ren void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::Render_RenderThread(FRHICommandListImmediate& RHICmdList, const TArray& RiveRenderCommands) { - // ID3D11DynamicRHI* D3D11RHI = GetID3D11DynamicRHI(); - // ID3D11Device* D3D11DevicePtr = D3D11RHI->RHIGetDevice(); - // ID3D11DeviceContext* D3D11DeviceContext = nullptr; - // D3D11DevicePtr->GetImmediateContext(&D3D11DeviceContext); - - // FRDGBuilder GraphBuilder(RHICmdList); - - // -- First, we start a render pass todo: might not be needed + // -- First, we start a render pass todo: might not be needed here FTextureRHIRef TargetTexture = RenderTarget->GetResource()->TextureRHI; RHICmdList.Transition(FRHITransitionInfo(TargetTexture, ERHIAccess::Unknown, ERHIAccess::RTV)); FRHIRenderPassInfo RPInfo(TargetTexture, ERenderTargetActions::Load_Store); RHICmdList.BeginRenderPass(RPInfo, TEXT("RiveRenderingTexture")); - // { - // FGlobalShaderMap* ShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel); - // TShaderMapRef VertexShader(ShaderMap); - // TShaderMapRef PixelShader(ShaderMap); - // - // FGraphicsPipelineStateInitializer GraphicsPSOInit; - // RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit); - // GraphicsPSOInit.BlendState = TStaticBlendState::GetRHI(); - // GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI(); - // GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState::GetRHI(); - // GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI; - // GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader(); - // GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader(); - // GraphicsPSOInit.PrimitiveType = PT_TriangleList; - // - // SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0); - // SetShaderParametersLegacyPS(RHICmdList, PixelShader, TStaticSamplerState::GetRHI(), TargetTexture); - // } - // RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread); - // -- Then we render Rive, ensuring the DX11 states are reset before the call RHICmdList.EnqueueLambda([this, RiveRenderCommands](FRHICommandListImmediate& RHICmdList) { RiveRendererD3D11->ResetDXStateForRive(); - FRiveRenderTarget::Render_Internal(RiveRenderCommands, &RHICmdList); + FRiveRenderTarget::Render_Internal(RiveRenderCommands); RiveRendererD3D11->ResetDXState(); }); - // RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread); - - - // ID3D11DynamicRHI* D3D11RHI = GetID3D11DynamicRHI(); - // if (IRHICommandContextPSOFallback* PsoFallback = (IRHICommandContextPSOFallback*)D3D11RHI) - // { - // PsoFallback->RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); - // PsoFallback->RHISetBlendState(TStaticBlendState::GetRHI(), FLinearColor(1.0f, 1.0f, 1.0f)); - // PsoFallback->RHISetDepthStencilState(TStaticDepthStencilState<>::GetRHI(), 0); - // } // -- Lastly, now that we have manually reset DX11, we need to update the state to ensure it matches the direct calls we just made { FGlobalShaderMap* ShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel); - TShaderMapRef VertexShader(ShaderMap); // just a default todo: might need to be forced set - TShaderMapRef PixelShader(ShaderMap); // just a default todo: might need to be forced set + TShaderMapRef VertexShader(ShaderMap); + TShaderMapRef PixelShader(ShaderMap); FGraphicsPipelineStateInitializer GraphicsPSOInit; RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit); @@ -135,37 +98,19 @@ void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::Render_RenderThread(FR GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI(); // NOT the same as default D3D11_DEPTH_STENCIL_DESC, a matching DepthStencil has been created in FRiveRendererD3D11GPUAdapter::InitBlendState GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState::GetRHI(); - GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI; // just a default todo: might need to be forced set + GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI; GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader(); GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader(); - GraphicsPSOInit.PrimitiveType = PT_TriangleList; // just a default todo: might need to be forced set + GraphicsPSOInit.PrimitiveType = PT_TriangleList; SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0, EApplyRendertargetOption::CheckApply, false); } RHICmdList.EndRenderPass(); RHICmdList.Transition(FRHITransitionInfo(TargetTexture, ERHIAccess::RTV, ERHIAccess::SRVMask)); - // RHICmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread); - - // GraphBuilder.Execute(); + } rive::rcp UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::GetRenderTarget() const { return CachedPLSRenderTargetD3D; } - -std::unique_ptr UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::BeginFrame(FRHICommandListImmediate* RHICmdListPtr) -{ - check(RHICmdListPtr); - check(RenderTarget->GetResource()->TextureRHI); - - return FRiveRenderTarget::BeginFrame(RHICmdListPtr); -} - -#if WITH_RIVE -void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::EndFrame(FRHICommandListImmediate* RHICmdListPtr) const -{ - FRiveRenderTarget::EndFrame(RHICmdListPtr); -} - -#endif // WITH_RIVE #endif // PLATFORM_WINDOWS diff --git a/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.h b/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.h index f806c694..4808a71d 100644 --- a/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.h +++ b/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.h @@ -44,9 +44,6 @@ namespace UE::Rive::Renderer::Private // It Might need to be on rendering thread, render QUEUE is required virtual void Render_RenderThread(FRHICommandListImmediate& RHICmdList, const TArray& RiveRenderCommands) override; virtual rive::rcp GetRenderTarget() const override; - virtual std::unique_ptr BeginFrame(FRHICommandListImmediate* RHICmdList) override; - virtual void EndFrame(FRHICommandListImmediate* RHICmdList) const override; - //~ END : FRiveRenderTarget Interface /** diff --git a/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp b/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp index fc47e96b..18a2f79a 100644 --- a/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp +++ b/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp @@ -6,7 +6,6 @@ #include "ID3D11DynamicRHI.h" #include "Logs/RiveRendererLog.h" #include "ProfilingDebugging/RealtimeGPUProfiler.h" -#include "D3D11State.h" #include "RiveRenderTargetD3D11.h" #include "Windows/D3D11ThirdParty.h" diff --git a/Source/RiveRenderer/Private/RiveRenderTarget.cpp b/Source/RiveRenderer/Private/RiveRenderTarget.cpp index f05cd8fb..79951b02 100644 --- a/Source/RiveRenderer/Private/RiveRenderTarget.cpp +++ b/Source/RiveRenderer/Private/RiveRenderTarget.cpp @@ -152,7 +152,7 @@ FMatrix UE::Rive::Renderer::Private::FRiveRenderTarget::GetTransformMatrix() con return CurrentMatrix; } -std::unique_ptr UE::Rive::Renderer::Private::FRiveRenderTarget::BeginFrame(FRHICommandListImmediate* RHICmdListPtr) +std::unique_ptr UE::Rive::Renderer::Private::FRiveRenderTarget::BeginFrame() { rive::pls::PLSRenderContext* PLSRenderContextPtr = RiveRenderer->GetPLSRenderContextPtr(); if (PLSRenderContextPtr == nullptr) @@ -182,7 +182,7 @@ std::unique_ptr UE::Rive::Renderer::Private::FRiveRender return std::make_unique(PLSRenderContextPtr); } -void UE::Rive::Renderer::Private::FRiveRenderTarget::EndFrame(FRHICommandListImmediate* RHICmdListPtr) const +void UE::Rive::Renderer::Private::FRiveRenderTarget::EndFrame() const { rive::pls::PLSRenderContext* PLSRenderContextPtr = RiveRenderer->GetPLSRenderContextPtr(); if (PLSRenderContextPtr == nullptr) @@ -215,10 +215,10 @@ void UE::Rive::Renderer::Private::FRiveRenderTarget::Render_RenderThread(FRHICom SCOPED_GPU_STAT(RHICmdList, Render); check(IsInRenderingThread()); - Render_Internal(RiveRenderCommands, &RHICmdList); + Render_Internal(RiveRenderCommands); } -void UE::Rive::Renderer::Private::FRiveRenderTarget::Render_Internal(const TArray& RiveRenderCommands, FRHICommandListImmediate* RHICmdListPtr) +void UE::Rive::Renderer::Private::FRiveRenderTarget::Render_Internal(const TArray& RiveRenderCommands) { FScopeLock Lock(&RiveRenderer->GetThreadDataCS()); @@ -234,7 +234,7 @@ void UE::Rive::Renderer::Private::FRiveRenderTarget::Render_Internal(const TArra #endif // Begin Frame - std::unique_ptr PLSRenderer = BeginFrame(RHICmdListPtr); + std::unique_ptr PLSRenderer = BeginFrame(); if (PLSRenderer == nullptr) { return; @@ -276,5 +276,5 @@ void UE::Rive::Renderer::Private::FRiveRenderTarget::Render_Internal(const TArra } } - EndFrame(RHICmdListPtr); + EndFrame(); } diff --git a/Source/RiveRenderer/Private/RiveRenderTarget.h b/Source/RiveRenderer/Private/RiveRenderTarget.h index c22b1cae..e3a615f2 100644 --- a/Source/RiveRenderer/Private/RiveRenderTarget.h +++ b/Source/RiveRenderer/Private/RiveRenderTarget.h @@ -60,10 +60,10 @@ namespace UE::Rive::Renderer::Private protected: virtual rive::rcp GetRenderTarget() const = 0; - virtual std::unique_ptr BeginFrame(FRHICommandListImmediate* RHICmdListPtr); - virtual void EndFrame(FRHICommandListImmediate* RHICmdListPtr) const; + virtual std::unique_ptr BeginFrame(); + virtual void EndFrame() const; virtual void Render_RenderThread(FRHICommandListImmediate& RHICmdList, const TArray& RiveRenderCommands); - virtual void Render_Internal(const TArray& RiveRenderCommands, FRHICommandListImmediate* RHICmdListPtr); + virtual void Render_Internal(const TArray& RiveRenderCommands); #endif // WITH_RIVE protected: From 94d729d6f31dbd9e7e7cfc73a1a1811fe81d10a3 Mon Sep 17 00:00:00 2001 From: "matthieu.begoghina" <12561988+Voulz@users.noreply.github.com> Date: Mon, 25 Mar 2024 23:55:27 +1100 Subject: [PATCH 5/5] DirectX11 fixes for UR-190 and UR-177 Properly handles DirectX11 states within UE, as well as proper handling of UAVs --- .../Platform/RiveRenderTargetD3D11.cpp | 35 ++------ .../Private/Platform/RiveRendererD3D11.cpp | 89 ++----------------- .../Private/Platform/RiveRendererD3D11.h | 18 +--- Source/RiveRenderer/RiveRenderer.Build.cs | 16 +++- 4 files changed, 26 insertions(+), 132 deletions(-) diff --git a/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp b/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp index e595195f..1f7327c0 100644 --- a/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp +++ b/Source/RiveRenderer/Private/Platform/RiveRenderTargetD3D11.cpp @@ -70,43 +70,18 @@ void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::CacheTextureTarget_Ren void UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::Render_RenderThread(FRHICommandListImmediate& RHICmdList, const TArray& RiveRenderCommands) { - // -- First, we start a render pass todo: might not be needed here + // First, we transition the texture to a RenderTextureView FTextureRHIRef TargetTexture = RenderTarget->GetResource()->TextureRHI; RHICmdList.Transition(FRHITransitionInfo(TargetTexture, ERHIAccess::Unknown, ERHIAccess::RTV)); - FRHIRenderPassInfo RPInfo(TargetTexture, ERenderTargetActions::Load_Store); - RHICmdList.BeginRenderPass(RPInfo, TEXT("RiveRenderingTexture")); - - // -- Then we render Rive, ensuring the DX11 states are reset before the call + // Then we render Rive, ensuring the DX11 states are reset before and after the call RHICmdList.EnqueueLambda([this, RiveRenderCommands](FRHICommandListImmediate& RHICmdList) { - RiveRendererD3D11->ResetDXStateForRive(); + RiveRendererD3D11->ResetDXState(); FRiveRenderTarget::Render_Internal(RiveRenderCommands); RiveRendererD3D11->ResetDXState(); }); - - // -- Lastly, now that we have manually reset DX11, we need to update the state to ensure it matches the direct calls we just made - { - FGlobalShaderMap* ShaderMap = GetGlobalShaderMap(GMaxRHIFeatureLevel); - TShaderMapRef VertexShader(ShaderMap); - TShaderMapRef PixelShader(ShaderMap); - - FGraphicsPipelineStateInitializer GraphicsPSOInit; - RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit); - // same as default D3D11_BLEND_DESC which is same as passing null to OMSetBlendState - GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI(); - // NOT the same as default D3D11_RASTERIZER_DESC, a matching Rasterizer has been created in FRiveRendererD3D11GPUAdapter::InitBlendState - GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI(); - // NOT the same as default D3D11_DEPTH_STENCIL_DESC, a matching DepthStencil has been created in FRiveRendererD3D11GPUAdapter::InitBlendState - GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState::GetRHI(); - GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GFilterVertexDeclaration.VertexDeclarationRHI; - GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader(); - GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader(); - GraphicsPSOInit.PrimitiveType = PT_TriangleList; - SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0, EApplyRendertargetOption::CheckApply, false); - } - RHICmdList.EndRenderPass(); - RHICmdList.Transition(FRHITransitionInfo(TargetTexture, ERHIAccess::RTV, ERHIAccess::SRVMask)); - + // Finally we transition the texture to a UAV Graphics + RHICmdList.Transition(FRHITransitionInfo(TargetTexture, ERHIAccess::RTV, ERHIAccess::UAVGraphics)); } rive::rcp UE::Rive::Renderer::Private::FRiveRenderTargetD3D11::GetRenderTarget() const diff --git a/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp b/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp index 18a2f79a..e61a8dcb 100644 --- a/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp +++ b/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.cpp @@ -8,6 +8,7 @@ #include "ProfilingDebugging/RealtimeGPUProfiler.h" #include "RiveRenderTargetD3D11.h" #include "Windows/D3D11ThirdParty.h" +#include "D3D11RHIPrivate.h" #if WITH_RIVE #include "RiveCore/Public/PreRiveHeaders.h" @@ -40,87 +41,16 @@ void UE::Rive::Renderer::Private::FRiveRendererD3D11GPUAdapter::Initialize(rive: AdapterDesc.VendorId == 0x8086 || AdapterDesc.VendorId == 0x8087; } } - - // Init Blend State to fix the issue with Slate UI rendering - InitBlendState(); } #endif // WITH_RIVE -void UE::Rive::Renderer::Private::FRiveRendererD3D11GPUAdapter::ResetDXStateForRive() -{ - if (!D3D11DeviceContext) - { - UE_LOG(LogRiveRenderer, Warning, TEXT("D3D11DeviceContext is nullptr while resetting the DirectX state")); - return; - } - - // Rive is resetting the Rasterizer and BlendState in PLSRenderContextD3DImpl::flush, so no need to call them - // the DepthStencil is not set by Rive, so we reset to default - D3D11DeviceContext->OMSetDepthStencilState(nullptr, 0); -} - void UE::Rive::Renderer::Private::FRiveRendererD3D11GPUAdapter::ResetDXState() { - if (!D3D11DeviceContext) + // Clear the internal state kept by UE and reset DX + FD3D11DynamicRHI* DynRHI = static_cast(D3D11RHI); + if (ensure(DynRHI)) { - UE_LOG(LogRiveRenderer, Warning, TEXT("D3D11DeviceContext is nullptr while resetting the DirectX state")); - return; - } - - // We don't need to set a BlendState because we can match the default with TStaticBlendState<>::GetRHI(); - D3D11DeviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF); - // We need a Rasterizer because the default state sets D3D11_RASTERIZER_DESC::FrontCounterClockwise to false, but UE sets it to true - D3D11DeviceContext->RSSetState(DefaultRasterState); - // We also need a DepthStencil because the default raster state states D3D11_DEPTH_STENCIL_DESC::DepthWriteMask to D3D11_DEPTH_WRITE_MASK_ALL, but UE crashed with that option - D3D11DeviceContext->OMSetDepthStencilState(DefaultDepthStencilState, 0); -} - -void UE::Rive::Renderer::Private::FRiveRendererD3D11GPUAdapter::InitBlendState() -{ - check(IsInRenderingThread()); - check(D3D11DevicePtr); - - // Below is matching TStaticRasterizerState<>::GetRHI(); - D3D11_RASTERIZER_DESC RasterDesc; - FMemory::Memzero(&RasterDesc,sizeof(D3D11_RASTERIZER_DESC)); - RasterDesc.CullMode = D3D11_CULL_NONE; - RasterDesc.FillMode = D3D11_FILL_SOLID; - RasterDesc.SlopeScaledDepthBias = 0.f; - RasterDesc.FrontCounterClockwise = true; - RasterDesc.DepthBias = 0.f; - RasterDesc.DepthClipEnable = true; - RasterDesc.MultisampleEnable = true; - RasterDesc.ScissorEnable = true; - - RasterDesc.AntialiasedLineEnable = false; - RasterDesc.DepthBiasClamp = 0.f; - - HRESULT Hr = D3D11DevicePtr->CreateRasterizerState(&RasterDesc, DefaultRasterState.GetInitReference()); - if (FAILED(Hr)) - { - UE_LOG(LogRiveRenderer, Warning, TEXT("D3D11DevicePtr->CreateRasterizerState( &RasterDesc, NormalRasterState.GetInitReference() ) Failed")); - } - - // Below is matching TStaticDepthStencilState::GetRHI(); - D3D11_DEPTH_STENCIL_DESC DepthStencilDesc; - FMemory::Memzero(&DepthStencilDesc,sizeof(D3D11_DEPTH_STENCIL_DESC)); - DepthStencilDesc.DepthEnable = true; // because DepthTest = CF_DepthNearOrEqual - DepthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; - DepthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; // CF_DepthNearOrEqual has no match - - DepthStencilDesc.StencilEnable = false; - DepthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS ; - DepthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; - DepthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; - DepthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - DepthStencilDesc.BackFace = DepthStencilDesc.FrontFace; - DepthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; - DepthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; - - Hr = D3D11DevicePtr->CreateDepthStencilState( &DepthStencilDesc, DefaultDepthStencilState.GetInitReference() ); - if (FAILED(Hr)) - { - UE_LOG(LogRiveRenderer, Warning, TEXT("D3D11DevicePtr->CreateDepthStencilState( &DepthStencilDesc, DepthStencilState.GetInitReference() ) Failed")); + DynRHI->ClearState(); } } @@ -167,15 +97,6 @@ void UE::Rive::Renderer::Private::FRiveRendererD3D11::CreatePLSRenderer_RenderTh RIVE_DEBUG_FUNCTION_INDENT; } -void UE::Rive::Renderer::Private::FRiveRendererD3D11::ResetDXStateForRive() const -{ - check(IsInRenderingThread()); - check(D3D11GPUAdapter.IsValid()); - - FScopeLock Lock(&ThreadDataCS); - D3D11GPUAdapter->ResetDXStateForRive(); -} - void UE::Rive::Renderer::Private::FRiveRendererD3D11::ResetDXState() const { check(IsInRenderingThread()); diff --git a/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.h b/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.h index 7070a0fc..154c5473 100644 --- a/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.h +++ b/Source/RiveRenderer/Private/Platform/RiveRendererD3D11.h @@ -35,24 +35,18 @@ namespace UE::Rive::Renderer::Private #if WITH_RIVE void Initialize(rive::pls::PLSRenderContextD3DImpl::ContextOptions& OutContextOptions); #endif // WITH_RIVE - void ResetDXStateForRive(); void ResetDXState(); ID3D11DynamicRHI* GetD3D11RHI() const { return D3D11RHI; } ID3D11Device* GetD3D11DevicePtr() const { return D3D11DevicePtr; } ID3D11DeviceContext* GetD3D11DeviceContext() const { return D3D11DeviceContext; } IDXGIDevice* GetDXGIDevice() const { return DXGIDevice; } - - private: - void InitBlendState(); + private: ID3D11DynamicRHI* D3D11RHI = nullptr; ID3D11Device* D3D11DevicePtr = nullptr; ID3D11DeviceContext* D3D11DeviceContext = nullptr; TRefCountPtr DXGIDevice = nullptr; - - TRefCountPtr DefaultDepthStencilState; - TRefCountPtr DefaultRasterState; }; class RIVERENDERER_API FRiveRendererD3D11 : public FRiveRenderer @@ -60,21 +54,13 @@ namespace UE::Rive::Renderer::Private /** * Structor(s) */ - public: //~ BEGIN : IRiveRenderer Interface - - public: - virtual IRiveRenderTargetPtr CreateTextureTarget_GameThread(const FName& InRiveName, UTexture2DDynamic* InRenderTarget) override; - virtual void CreatePLSContext_RenderThread(FRHICommandListImmediate& RHICmdList) override; - virtual void CreatePLSRenderer_RenderThread(FRHICommandListImmediate& RHICmdList) override; - //~ END : IRiveRenderer Interface - - void ResetDXStateForRive() const; + void ResetDXState() const; private: diff --git a/Source/RiveRenderer/RiveRenderer.Build.cs b/Source/RiveRenderer/RiveRenderer.Build.cs index 6863cec2..3b35d452 100644 --- a/Source/RiveRenderer/RiveRenderer.Build.cs +++ b/Source/RiveRenderer/RiveRenderer.Build.cs @@ -46,10 +46,22 @@ public RiveRenderer(ReadOnlyTargetRules Target) : base(Target) if (Target.Platform.IsInGroup(UnrealPlatformGroup.Windows)) { - PublicIncludePathModuleNames.AddAll("D3D11RHI"); // , "D3D12RHI"); + PublicDependencyModuleNames.Add("D3D11RHI"); + PublicIncludePathModuleNames.AddAll("RHICore", "D3D11RHI"); // , "D3D12RHI"); AddEngineThirdPartyPrivateStaticDependencies(Target, "DX11"); - // AddEngineThirdPartyPrivateStaticDependencies(Target, "DX12"); + // AddEngineThirdPartyPrivateStaticDependencies(Target, "DX12"); + + // Adding the path needed to include the private file D3D11RHIPrivate.h + string enginePath = Path.GetFullPath(Target.RelativeEnginePath); + string sourcePath = Path.Combine(enginePath, "Source", "Runtime"); + PrivateIncludePaths.Add(Path.Combine(sourcePath, "Windows", "D3D11RHI", "Private")); + PublicIncludePaths.Add(Path.Combine(sourcePath, "Windows", "D3D11RHI", "Private")); + + // Copied from D3D11RHI.build.cs, needed to include the private file D3D11RHIPrivate.h + AddEngineThirdPartyPrivateStaticDependencies(Target, "IntelExtensionsFramework"); + AddEngineThirdPartyPrivateStaticDependencies(Target, "IntelMetricsDiscovery"); + AddEngineThirdPartyPrivateStaticDependencies(Target, "NVAftermath"); } else if (Target.Platform.IsInGroup(UnrealPlatformGroup.Android)) {