Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ option(BUILD_AS_SHARED "Build as dll skse plugin else build as static lib" ON)

# Version
set(LIB_MAJOR_VERSION 3)
set(LIB_MINOR_VERSION 2)
set(LIB_MINOR_VERSION 3)
set(API_MAJOR_VERSION 3)
set(API_MINOR_VERSION 2)
set(API_MINOR_VERSION 3)

# VCPKG config
string(REPLACE "\\" "/" ENV_VCPKG_ROOT "$ENV{VCPKG_ROOT}")
Expand Down
3 changes: 3 additions & 0 deletions src/UIPlatform/CEF/NirnLabCefApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ namespace NL::CEF

// command_line->AppendSwitch("disable-gpu-vsync");

// Disables lazy loading of images and frames
// command_line->AppendSwitch("disable-lazy-loading");

// Most systems would not need to use this switch - but on older hardware,
// Chromium may still choose to disable D3D11 for gpu workarounds.
// Accelerated OSR will not at all with D3D11 disabled, so we force it on.
Expand Down
2 changes: 1 addition & 1 deletion src/UIPlatform/CEF/NirnLabCefClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace NL::CEF
{
NirnLabCefClient::NirnLabCefClient()
{
m_cefRenderLayer = NL::Render::CEFCopyRenderLayer::make_shared();
m_cefRenderLayer = NL::Render::CEFSyncCopyRenderLayer::make_shared();
}

std::shared_ptr<NL::Render::IRenderLayer> NirnLabCefClient::GetRenderLayer()
Expand Down
4 changes: 2 additions & 2 deletions src/UIPlatform/CEF/NirnLabCefClient.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include "PCH.h"
#include "Render/CEFCopyRenderLayer.h"
#include "Render/CEFSyncCopyRenderLayer.h"
#include "Render/CEFRenderLayer.h"

namespace NL::CEF
Expand All @@ -14,7 +14,7 @@ namespace NL::CEF
IMPLEMENT_REFCOUNTING(NirnLabCefClient);

protected:
std::shared_ptr<NL::Render::CEFCopyRenderLayer> m_cefRenderLayer = nullptr;
std::shared_ptr<NL::Render::CEFSyncCopyRenderLayer> m_cefRenderLayer = nullptr;
CefRefPtr<CefBrowser> m_cefBrowser = nullptr;

public:
Expand Down
8 changes: 4 additions & 4 deletions src/UIPlatform/NirnLabUIPlatformAPI/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
namespace NL::UI::LibVersion
{
inline constexpr std::uint32_t MAJOR = 3;
inline constexpr std::uint32_t MINOR = 2;
inline constexpr std::uint32_t MINOR = 3;
inline constexpr auto PROJECT_NAME = "NirnLabUIPlatform";

inline constexpr auto MAJOR_MULT = 100000;
inline constexpr auto AS_STRING = "3.2";
inline constexpr auto AS_STRING = "3.3";
inline constexpr std::uint32_t AS_INT = (static_cast<std::uint32_t>(MAJOR * MAJOR_MULT + MINOR));

inline std::uint32_t GetMajorVersion(std::uint32_t a_version)
Expand All @@ -26,10 +26,10 @@ namespace NL::UI::LibVersion
namespace NL::UI::APIVersion
{
inline constexpr std::uint32_t MAJOR = 3;
inline constexpr std::uint32_t MINOR = 2;
inline constexpr std::uint32_t MINOR = 3;

inline constexpr auto MAJOR_MULT = 100000;
inline constexpr auto AS_STRING = "3.2";
inline constexpr auto AS_STRING = "3.3";
inline constexpr std::uint32_t AS_INT = (static_cast<std::uint32_t>(MAJOR * MAJOR_MULT + MINOR));

inline std::uint32_t GetMajorVersion(std::uint32_t a_version)
Expand Down
175 changes: 175 additions & 0 deletions src/UIPlatform/Render/CEFSyncCopyRenderLayer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
#include "CEFSyncCopyRenderLayer.h"

namespace NL::Render
{
std::shared_ptr<CEFSyncCopyRenderLayer> CEFSyncCopyRenderLayer::make_shared()
{
const auto cefRender = new CEFSyncCopyRenderLayer();
cefRender->AddRef();
return std::shared_ptr<CEFSyncCopyRenderLayer>(cefRender, CEFSyncCopyRenderLayer::release_shared);
}

void CEFSyncCopyRenderLayer::release_shared(CEFSyncCopyRenderLayer* a_render)
{
a_render->Release();
}

CEFSyncCopyRenderLayer::AtomicFlagGuard::AtomicFlagGuard(std::atomic_flag& a_flag)
: m_flag(a_flag)
{
}

CEFSyncCopyRenderLayer::AtomicFlagGuard::~AtomicFlagGuard()
{
m_flag.clear(std::memory_order_release);
m_flag.notify_all();
}

void CEFSyncCopyRenderLayer::CopySharedTexure()
{
Microsoft::WRL::ComPtr<ID3D11Texture2D> sharedTexture = nullptr;
auto hr = m_device1->OpenSharedResource1(m_acceleratedPaintInfo->shared_texture_handle, IID_PPV_ARGS(sharedTexture.ReleaseAndGetAddressOf()));
FAST_CHECK_HRESULT_LOG_AND_RETURN(hr, "CEFSyncCopyRenderLayer::CopySharedTexure() - OpenSharedResource1()");

if (m_cefSRV == nullptr)
{
D3D11_TEXTURE2D_DESC sharedTextureDesc = {};
sharedTexture->GetDesc(&sharedTextureDesc);

hr = m_renderData->device->CreateTexture2D(&sharedTextureDesc, nullptr, m_cefTexture.ReleaseAndGetAddressOf());
FAST_CHECK_HRESULT_LOG_AND_RETURN(hr, "CEFSyncCopyRenderLayer::CopySharedTexure() - CreateTexture2D()");

D3D11_SHADER_RESOURCE_VIEW_DESC sharedResourceViewDesc = {};
sharedResourceViewDesc.Format = sharedTextureDesc.Format;
sharedResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
sharedResourceViewDesc.Texture2D.MostDetailedMip = 0;
sharedResourceViewDesc.Texture2D.MipLevels = 1;

hr = m_renderData->device->CreateShaderResourceView(m_cefTexture.Get(), &sharedResourceViewDesc, m_cefSRV.ReleaseAndGetAddressOf());
FAST_CHECK_HRESULT_LOG_AND_RETURN(hr, "CEFSyncCopyRenderLayer::CopySharedTexure() - CreateShaderResourceView()");

spdlog::info("CEFSyncCopyRenderLayer: texture created");
}

D3D11_BOX dirtyRect;
dirtyRect.left = m_acceleratedPaintInfo->extra.capture_update_rect.x;
dirtyRect.top = m_acceleratedPaintInfo->extra.capture_update_rect.y;
dirtyRect.right = m_acceleratedPaintInfo->extra.capture_update_rect.x + m_acceleratedPaintInfo->extra.capture_update_rect.width;
dirtyRect.bottom = m_acceleratedPaintInfo->extra.capture_update_rect.y + m_acceleratedPaintInfo->extra.capture_update_rect.height;
dirtyRect.front = 0;
dirtyRect.back = 1;

m_renderData->deviceContext->CopySubresourceRegion(m_cefTexture.Get(),
0,
m_acceleratedPaintInfo->extra.capture_update_rect.x,
m_acceleratedPaintInfo->extra.capture_update_rect.y,
0,
sharedTexture.Get(),
0,
&dirtyRect);
// The CopyResource call is asynchronous by default
m_renderData->deviceContext->Flush();

D3D11_QUERY_DESC queryDesc = {};
queryDesc.Query = D3D11_QUERY_EVENT;
queryDesc.MiscFlags = 0;

Microsoft::WRL::ComPtr<ID3D11Query> query;
hr = m_device1->CreateQuery(&queryDesc, &query);
FAST_CHECK_HRESULT_LOG_AND_RETURN(hr, "CEFSyncCopyRenderLayer::CopySharedTexure() - CreateQuery()");

m_renderData->deviceContext->End(query.Get());

while (S_FALSE == m_renderData->deviceContext->GetData(query.Get(), NULL, 0, 0))
{
}
}

void CEFSyncCopyRenderLayer::Init(RenderData* a_renderData)
{
IRenderLayer::Init(a_renderData);

const auto hr = m_renderData->device->QueryInterface(IID_PPV_ARGS(&m_device1));
if (FAILED(hr))
{
spdlog::error("CEFSyncCopyRenderLayer::Init() - failed QueryInterface(), code {:X}", hr);
}
}

const inline ::DirectX::SimpleMath::Vector2 _Cef_Menu_Draw_Vector = {0.f, 0.f};
void CEFSyncCopyRenderLayer::Draw()
{
if (m_acceleratedPaintReady.test(std::memory_order_acquire))
{
AtomicFlagGuard guard(m_acceleratedPaintReady);
CopySharedTexure();
}

if (m_isVisible && m_cefSRV != nullptr)
{
m_renderData->spriteBatch->Draw(
m_cefSRV.Get(),
_Cef_Menu_Draw_Vector,
nullptr,
::DirectX::Colors::White,
0.f);
}
}

void CEFSyncCopyRenderLayer::GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect)
{
if (m_renderData)
{
rect.x = 0;
rect.y = 0;
rect.width = m_renderData->width;
rect.height = m_renderData->height;
}
else
{
rect.x = 0;
rect.y = 0;
rect.width = 800;
rect.height = 600;
}
}

void CEFSyncCopyRenderLayer::OnPaint(CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
const void* buffer,
int width,
int height)
{
spdlog::error("CEFCopyRenderLayer::OnPaint called");
}

void CEFSyncCopyRenderLayer::OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
const CefAcceleratedPaintInfo& info)
{
if (type == PaintElementType::PET_POPUP)
{
return;
}

if (m_renderData == nullptr ||
m_device1 == nullptr)
{
spdlog::error("CEFSyncCopyRenderLayer::OnAcceleratedPaint() - device or renderData is nullptr");
return;
}

m_acceleratedPaintInfo = &info;
m_acceleratedPaintReady.test_and_set(std::memory_order_acquire);
while (m_acceleratedPaintReady.test(std::memory_order_acquire))
{
if (NL::Hooks::ShutdownHook::IsGameClosing)
{
m_acceleratedPaintReady.clear(std::memory_order_release);
break;
}
}
}
}
57 changes: 57 additions & 0 deletions src/UIPlatform/Render/CEFSyncCopyRenderLayer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma once

#include "PCH.h"
#include "IRenderLayer.h"
#include "Hooks/ShutdownHook.hpp"

namespace NL::Render
{
class CEFSyncCopyRenderLayer : public IRenderLayer,
public CefRenderHandler
{
IMPLEMENT_REFCOUNTING(CEFSyncCopyRenderLayer);

public:
static std::shared_ptr<CEFSyncCopyRenderLayer> make_shared();
static void release_shared(CEFSyncCopyRenderLayer* a_render);

protected:
struct AtomicFlagGuard
{
std::atomic_flag& m_flag;

AtomicFlagGuard(std::atomic_flag& a_flag);
~AtomicFlagGuard();
};

Microsoft::WRL::ComPtr<ID3D11Device1> m_device1 = nullptr;
Microsoft::WRL::ComPtr<ID3D11Texture2D> m_cefTexture = nullptr;
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_cefSRV = nullptr;
const CefAcceleratedPaintInfo* m_acceleratedPaintInfo = nullptr;
std::atomic_flag m_acceleratedPaintReady = ATOMIC_FLAG_INIT;

void CopySharedTexure();

public:
virtual ~CEFSyncCopyRenderLayer() override = default;

// IRenderLayer
void Init(RenderData* a_renderData) override;
void Draw() override;

// CefRenderHandler
void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override;
void OnPaint(
CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
const void* buffer,
int width,
int height) override;
void OnAcceleratedPaint(
CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
const CefAcceleratedPaintInfo& info) override;
};
}
10 changes: 10 additions & 0 deletions src/UIPlatform/Utils/CheckHresult.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,13 @@ inline void CheckHresultThrow(HRESULT hr, const std::string& userMsg)
return; \
} \
} while (0)

#define FAST_CHECK_HRESULT_LOG_AND_RETURN(hr, userMsg) \
do \
{ \
if (FAILED(hr)) \
{ \
spdlog::error("{}", CheckHresultMessage(hr, userMsg)); \
return; \
} \
} while (0)
8 changes: 4 additions & 4 deletions src/UIPlatformTest/NirnLabUIPlatformAPI/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
namespace NL::UI::LibVersion
{
inline constexpr std::uint32_t MAJOR = 3;
inline constexpr std::uint32_t MINOR = 2;
inline constexpr std::uint32_t MINOR = 3;
inline constexpr auto PROJECT_NAME = "NirnLabUIPlatform";

inline constexpr auto MAJOR_MULT = 100000;
inline constexpr auto AS_STRING = "3.2";
inline constexpr auto AS_STRING = "3.3";
inline constexpr std::uint32_t AS_INT = (static_cast<std::uint32_t>(MAJOR * MAJOR_MULT + MINOR));

inline std::uint32_t GetMajorVersion(std::uint32_t a_version)
Expand All @@ -26,10 +26,10 @@ namespace NL::UI::LibVersion
namespace NL::UI::APIVersion
{
inline constexpr std::uint32_t MAJOR = 3;
inline constexpr std::uint32_t MINOR = 2;
inline constexpr std::uint32_t MINOR = 3;

inline constexpr auto MAJOR_MULT = 100000;
inline constexpr auto AS_STRING = "3.2";
inline constexpr auto AS_STRING = "3.3";
inline constexpr std::uint32_t AS_INT = (static_cast<std::uint32_t>(MAJOR * MAJOR_MULT + MINOR));

inline std::uint32_t GetMajorVersion(std::uint32_t a_version)
Expand Down
6 changes: 3 additions & 3 deletions src/UIPlatformTest/TestCases/LoadYoutubeTestCase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ namespace NL::UI::TestCase
{
void LoadYoutubeTestCase::Start(NL::UI::IUIPlatformAPI* a_api)
{
NL::UI::BrowserSettings bSettings;
bSettings.frameRate = 30;
NL::UI::BrowserSettings bSettings{};
// bSettings.frameRate = 30;

//m_browserHandle = a_api->AddOrGetBrowser("YOUTUBE_TEST_CEF", nullptr, 0, "https://youtube.com", m_browser);
// m_browserHandle = a_api->AddOrGetBrowser("YOUTUBE_TEST_CEF", nullptr, 0, "https://youtube.com", m_browser);
m_browserHandle = a_api->AddOrGetBrowser("YOUTUBE_TEST_CEF", nullptr, 0, "https://google.com", &bSettings, m_browser);

if (m_browserHandle == NL::UI::IUIPlatformAPI::InvalidBrowserRefHandle)
Expand Down
4 changes: 2 additions & 2 deletions src/UIPlatformTest/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ void Init1stMethodToGetAPI()
case SKSE::MessagingInterface::kInputLoaded:
if (s_canUseAPI)
{
NL::UI::Settings defaultSettings;
NL::UI::Settings defaultSettings{};
// API version is ok. Request interface.
SKSE::GetMessagingInterface()->Dispatch(NL::UI::APIMessageType::RequestAPI, &defaultSettings, sizeof(defaultSettings), NL::UI::LibVersion::PROJECT_NAME);
}
Expand Down Expand Up @@ -119,7 +119,7 @@ void Init2ndMethodToGetAPI()
try
{
NL::UI::IUIPlatformAPI* api = nullptr;
NL::UI::Settings defaultSettings;
NL::UI::Settings defaultSettings{};

if (NL::UI::DllLoader::CreateOrGetUIPlatformAPIWithVersionCheck(&api, &defaultSettings, NL::UI::APIVersion::AS_INT, PLUGIN_NAME))
{
Expand Down