VideoPresenter: Fix prerotation handling with blur/transitions

pull/3792/head
Stenzek 4 weeks ago
parent fe2306b1f0
commit 9287950af2
No known key found for this signature in database

@ -1230,12 +1230,13 @@ FullscreenUI::TransitionState FullscreenUI::GetTransitionState()
GPUTexture* FullscreenUI::GetTransitionRenderTexture(GPUSwapChain* const swap_chain)
{
if (!g_gpu_device->ResizeTexture(&s_state.transition_current_texture, swap_chain->GetWidth(), swap_chain->GetHeight(),
const u32 swap_chain_width = swap_chain->GetPostRotatedWidth();
const u32 swap_chain_height = swap_chain->GetPostRotatedHeight();
if (!g_gpu_device->ResizeTexture(&s_state.transition_current_texture, swap_chain_width, swap_chain_height,
GPUTexture::Type::RenderTarget, swap_chain->GetFormat(), GPUTexture::Flags::None,
false))
{
ERROR_LOG("Failed to allocate {}x{} texture for transition, cancelling.", swap_chain->GetWidth(),
swap_chain->GetHeight());
ERROR_LOG("Failed to allocate {}x{} texture for transition, cancelling.", swap_chain_width, swap_chain_height);
s_state.transition_state = TransitionState::Inactive;
return nullptr;
}
@ -1451,11 +1452,10 @@ void FullscreenUI::RenderTransitionBlend(GPUSwapChain* swap_chain, GPUTexture* c
g_gpu_device->SetViewportAndScissor(0, 0, swap_chain->GetPostRotatedWidth(), swap_chain->GetPostRotatedHeight());
const GSVector2i size = swap_chain->GetSizeVec();
const GSVector2i postrotated_size = swap_chain->GetPostRotatedSizeVec();
const GSVector4 uv_rect = g_gpu_device->UsesLowerLeftOrigin() ? GSVector4::cxpr(0.0f, 1.0f, 1.0f, 0.0f) :
GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f);
VideoPresenter::DrawScreenQuad(GSVector4i::loadh(size), uv_rect, size, postrotated_size, DisplayRotation::Normal,
swap_chain->GetPreRotation(), uniforms, sizeof(uniforms));
VideoPresenter::DrawScreenQuad(GSVector4i::loadh(size), uv_rect, size, size, DisplayRotation::Normal,
WindowInfoPrerotation::Identity, uniforms, sizeof(uniforms));
}
void FullscreenUI::UpdateTransitionState()
@ -1493,7 +1493,7 @@ void FullscreenUI::InvalidateBlurBackground()
s_state.blur_valid = false;
}
GPUTexture* FullscreenUI::GetBlurRenderTexture()
GPUTexture* FullscreenUI::GetBlurRenderTexture(GPUSwapChain* const swap_chain)
{
if (!s_state.blur_active)
return nullptr;
@ -1501,10 +1501,6 @@ GPUTexture* FullscreenUI::GetBlurRenderTexture()
// clear for next frame
s_state.blur_active = false;
const GPUSwapChain* const swap_chain = g_gpu_device->GetMainSwapChain();
if (!swap_chain)
return nullptr;
const u32 swap_chain_width = swap_chain->GetPostRotatedWidth();
const u32 swap_chain_height = swap_chain->GetPostRotatedHeight();
u32 blur_width, blur_height;
@ -1542,7 +1538,7 @@ GPUTexture* FullscreenUI::GetBlurRenderTexture()
}
s_state.blur_texture_scale =
GSVector2(s_state.blur_output_texture->GetSizeVec()) / GSVector2(swap_chain->GetSizeVec());
GSVector2(s_state.blur_output_texture->GetSizeVec()) / GSVector2(s_state.blur_source_texture->GetSizeVec());
s_state.blur_valid = false;
}
@ -1551,7 +1547,7 @@ GPUTexture* FullscreenUI::GetBlurRenderTexture()
return s_state.blur_valid ? nullptr : s_state.blur_source_texture.get();
}
void FullscreenUI::RenderBlur(GPUTexture* const blur_render_texture)
void FullscreenUI::RenderBlur(GPUSwapChain* const swap_chain, GPUTexture* const blur_render_texture)
{
DebugAssert(s_state.blur_source_texture && s_state.blur_source_texture.get() == blur_render_texture);
DebugAssert(s_state.blur_intermediate_texture);
@ -1566,11 +1562,13 @@ void FullscreenUI::RenderBlur(GPUTexture* const blur_render_texture)
const GSVector2i source_size_vec = s_state.blur_source_texture->GetSizeVec();
const GSVector2i size_vec = s_state.blur_output_texture->GetSizeVec();
const GSVector4i viewport = GSVector4i::loadh(size_vec);
const GSVector4 scaled_blur_rectf = GSVector4(s_state.blur_rect) * GSVector4::xyxy(s_state.blur_texture_scale);
const GSVector4 blur_rect = GSVector4(
GPUSwapChain::PreRotateClipRect(swap_chain->GetPreRotation(), swap_chain->GetSizeVec(), s_state.blur_rect));
const GSVector4 scaled_blur_rectf = blur_rect * GSVector4::xyxy(s_state.blur_texture_scale);
const GSVector4i scaled_blur_rect = GSVector4i(scaled_blur_rectf.floor().blend32<12>(scaled_blur_rectf.ceil()));
const GSVector2 texel_size = GSVector2::cxpr(1.0f) / GSVector2(size_vec);
GL_SCOPE_FMT("RenderDisplayBlur() Rect={}, ScaledRect={}", s_state.blur_rect, scaled_blur_rect);
GL_SCOPE_FMT("RenderDisplayBlur() Rect={}, ScaledRect={}", blur_rect, scaled_blur_rect);
blur_render_texture->MakeReadyForSampling();
g_gpu_device->SetViewport(viewport);
@ -6683,20 +6681,22 @@ void FullscreenUI::RenderLoadingScreen(std::string_view image, std::string_view
draw_data.Textures = &io.Fonts->TexList;
draw_data.AddDrawList(&draw_list);
GPUSwapChain* const swap_chain = g_gpu_device->GetMainSwapChain();
if (s_state.blur_active && !s_state.blur_valid)
{
GPUTexture* const blur_target = GetBlurRenderTexture();
GPUTexture* const blur_target = GetBlurRenderTexture(swap_chain);
if (blur_target)
{
VideoPresenter::RenderDisplay(blur_target, blur_target->GetSizeVec(), false, true);
RenderBlur(blur_target);
VideoPresenter::RenderDisplay(blur_target, blur_target->GetSizeVec(), swap_chain->GetPostRotatedSizeVec(),
swap_chain->GetPreRotation(), false, true);
RenderBlur(swap_chain, blur_target);
}
}
GPUSwapChain* swap_chain = g_gpu_device->GetMainSwapChain();
if (g_gpu_device->BeginPresent(swap_chain) == GPUPresentResult::OK)
{
ImGuiManager::RenderDrawLists(&draw_data, swap_chain);
ImGuiManager::RenderDrawLists(&draw_data, swap_chain->GetWidth(), swap_chain->GetHeight(),
swap_chain->GetPreRotation());
g_gpu_device->EndPresent(swap_chain, false);
}
}

@ -314,8 +314,8 @@ void UpdateTransitionState();
/// Screen blurring.
bool CanBlurBackground();
void InvalidateBlurBackground();
GPUTexture* GetBlurRenderTexture();
void RenderBlur(GPUTexture* const blur_render_texture);
GPUTexture* GetBlurRenderTexture(GPUSwapChain* const swap_chain);
void RenderBlur(GPUSwapChain* const swap_chain, GPUTexture* const blur_render_texture);
bool BeginBlurBackground(ImDrawList* const dl, const ImVec2& bb_min, const ImVec2& bb_max);
void EndBlurBackground(ImDrawList* const dl);

@ -592,8 +592,9 @@ void VideoPresenter::SetDisplayTexture(GPUTexture* texture, const GSVector4i& so
FullscreenUI::InvalidateBlurBackground();
}
GPUPresentResult VideoPresenter::RenderDisplay(GPUTexture* target, const GSVector2i target_size, bool postfx,
bool apply_aspect_ratio)
GPUPresentResult VideoPresenter::RenderDisplay(GPUTexture* target, const GSVector2i target_size,
const GSVector2i final_target_size, WindowInfoPrerotation prerotation,
bool postfx, bool apply_aspect_ratio)
{
GL_SCOPE_FMT("RenderDisplay: {}x{}", target_size.x, target_size.y);
@ -604,8 +605,6 @@ GPUPresentResult VideoPresenter::RenderDisplay(GPUTexture* target, const GSVecto
DebugAssert(!postfx || target_size.eq(g_gpu_device->GetMainSwapChain()->GetSizeVec()));
GPUSwapChain* const swap_chain = g_gpu_device->GetMainSwapChain();
const WindowInfoPrerotation prerotation = target ? WindowInfoPrerotation::Identity : swap_chain->GetPreRotation();
const GSVector2i final_target_size = target ? target->GetSizeVec() : swap_chain->GetPostRotatedSizeVec();
const bool is_vram_view = g_gpu_settings.gpu_show_vram;
const bool integer_scale = g_gpu_settings.IsUsingIntegerDisplayScaling(s_locals.display_texture_24bit);
const bool have_overlay = (postfx && !is_vram_view && HasBorderOverlay());
@ -1158,16 +1157,14 @@ GPUPresentResult VideoPresenter::DrawDisplayCopy(GPUTexture* const source, GPUTe
return pres;
}
const WindowInfoPrerotation prerotation = target ? WindowInfoPrerotation::Identity : swap_chain->GetPreRotation();
const GSVector2i final_target_size = target ? target->GetSizeVec() : swap_chain->GetPostRotatedSizeVec();
const GSVector2i target_size = target ? target->GetSizeVec() : swap_chain->GetSizeVec();
const GSVector4i rect = GSVector4i::loadh(target_size);
const GSVector2i size = target ? target->GetSizeVec() : swap_chain->GetPostRotatedSizeVec();
const GSVector4i rect = GSVector4i::loadh(size);
const GSVector4 uv_rect = g_gpu_device->UsesLowerLeftOrigin() ? GSVector4::cxpr(0.0f, 1.0f, 1.0f, 0.0f) :
GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f);
g_gpu_device->SetViewportAndScissor(rect);
g_gpu_device->SetTextureSampler(0, source, g_gpu_device->GetNearestSampler());
g_gpu_device->SetPipeline(FullscreenUI::GetPresentCopyPipeline());
DrawScreenQuad(rect, uv_rect, target_size, final_target_size, DisplayRotation::Normal, prerotation, nullptr, 0);
DrawScreenQuad(rect, uv_rect, size, size, DisplayRotation::Normal, WindowInfoPrerotation::Identity, nullptr, 0);
return GPUPresentResult::OK;
}
@ -1188,7 +1185,8 @@ void VideoPresenter::SendDisplayToMediaCapture(MediaCapture* cap)
(g_gpu_settings.display_screenshot_mode == DisplayScreenshotMode::ScreenResolution &&
g_gpu_device->HasMainSwapChain() && target->GetSizeVec().eq(g_gpu_device->GetMainSwapChain()->GetSizeVec()));
if (RenderDisplay(target, target->GetSizeVec(), postfx, apply_aspect_ratio) != GPUPresentResult::OK ||
if (RenderDisplay(target, target->GetSizeVec(), target->GetSizeVec(), WindowInfoPrerotation::Identity, postfx,
apply_aspect_ratio) != GPUPresentResult::OK ||
!cap->DeliverVideoFrame(target)) [[unlikely]]
{
WARNING_LOG("Failed to render/deliver video capture frame.");
@ -1509,11 +1507,12 @@ bool VideoPresenter::PresentFrame(GPUBackend* backend, u64 present_time)
GPUSwapChain* const swap_chain = g_gpu_device->GetMainSwapChain();
DebugAssert(swap_chain);
GPUTexture* const blur_target = FullscreenUI::GetBlurRenderTexture();
GPUTexture* const blur_target = FullscreenUI::GetBlurRenderTexture(swap_chain);
if (blur_target)
{
RenderDisplay(blur_target, blur_target->GetSizeVec(), true, true);
FullscreenUI::RenderBlur(blur_target);
RenderDisplay(blur_target, swap_chain->GetSizeVec(), swap_chain->GetPostRotatedSizeVec(),
swap_chain->GetPreRotation(), true, true);
FullscreenUI::RenderBlur(swap_chain, blur_target);
}
GPUPresentResult pres;
@ -1531,13 +1530,19 @@ bool VideoPresenter::PresentFrame(GPUBackend* backend, u64 present_time)
{
// Display still needs rendering.
if (backend)
RenderDisplay(transition_target, transition_target->GetSizeVec(), true, true);
{
RenderDisplay(transition_target, swap_chain->GetSizeVec(), swap_chain->GetPostRotatedSizeVec(),
swap_chain->GetPreRotation(), true, true);
}
else
{
g_gpu_device->ClearRenderTarget(transition_target, GPUDevice::DEFAULT_CLEAR_COLOR);
}
}
g_gpu_device->SetRenderTarget(transition_target);
ImGuiManager::RenderDrawLists(ImGui::GetDrawData(), transition_target);
ImGuiManager::RenderDrawLists(ImGui::GetDrawData(), swap_chain->GetWidth(), swap_chain->GetHeight(),
swap_chain->GetPreRotation());
if ((pres = g_gpu_device->BeginPresent(swap_chain)) == GPUPresentResult::OK)
FullscreenUI::RenderTransitionBlend(swap_chain, transition_target);
@ -1545,9 +1550,11 @@ bool VideoPresenter::PresentFrame(GPUBackend* backend, u64 present_time)
else
{
if ((pres = blur_target ? DrawDisplayCopy(blur_target, nullptr, swap_chain) :
RenderDisplay(nullptr, swap_chain->GetSizeVec(), true, true)) == GPUPresentResult::OK)
RenderDisplay(nullptr, swap_chain->GetSizeVec(), swap_chain->GetPostRotatedSizeVec(),
swap_chain->GetPreRotation(), true, true)) == GPUPresentResult::OK)
{
ImGuiManager::RenderDrawLists(ImGui::GetDrawData(), swap_chain);
ImGuiManager::RenderDrawLists(ImGui::GetDrawData(), swap_chain->GetWidth(), swap_chain->GetHeight(),
swap_chain->GetPreRotation());
}
}
@ -1632,8 +1639,8 @@ bool VideoPresenter::RenderScreenshotToBuffer(u32 width, u32 height, bool postfx
return false;
g_gpu_device->ClearRenderTarget(render_texture.get(), GPUDevice::DEFAULT_CLEAR_COLOR);
if (RenderDisplay(render_texture.get(), render_texture->GetSizeVec(), postfx, apply_aspect_ratio) !=
GPUPresentResult::OK)
if (RenderDisplay(render_texture.get(), render_texture->GetSizeVec(), render_texture->GetSizeVec(),
WindowInfoPrerotation::Identity, postfx, apply_aspect_ratio) != GPUPresentResult::OK)
{
Error::SetStringView(error, "RenderDisplay() failed");
return false;

@ -74,7 +74,8 @@ void ThrottlePresentation();
bool PresentFrame(GPUBackend* backend, u64 present_time);
/// Renders the display to the specified target. Use when you need to render it offscreen for another purpose.
GPUPresentResult RenderDisplay(GPUTexture* target, const GSVector2i target_size, bool postfx, bool apply_aspect_ratio);
GPUPresentResult RenderDisplay(GPUTexture* target, const GSVector2i target_size, const GSVector2i final_target_size,
WindowInfoPrerotation prerotation, bool postfx, bool apply_aspect_ratio);
/// Returns a list of border overlay presets.
std::vector<std::string> EnumerateBorderOverlayPresets();

@ -97,8 +97,6 @@ static bool LoadFontData(Error* error);
static void ReloadFontDataIfActive();
static bool CreateFontAtlas(Error* error);
static bool CompilePipelines(Error* error);
static void RenderDrawLists(const ImDrawData* draw_data, u32 window_width, u32 window_height,
WindowInfoPrerotation prerotation);
static void UpdateTextures(const ImDrawData* draw_data);
static void DestroyTextures(bool recycle);
static void SetCommonIOOptions(ImGuiIO& io, ImGuiPlatformIO& pio);
@ -694,16 +692,6 @@ void ImGuiManager::RenderDrawLists(const ImDrawData* draw_data, u32 window_width
}
}
void ImGuiManager::RenderDrawLists(const ImDrawData* draw_data, GPUSwapChain* swap_chain)
{
RenderDrawLists(draw_data, swap_chain->GetWidth(), swap_chain->GetHeight(), swap_chain->GetPreRotation());
}
void ImGuiManager::RenderDrawLists(const ImDrawData* draw_data, GPUTexture* texture)
{
RenderDrawLists(draw_data, texture->GetWidth(), texture->GetHeight(), WindowInfoPrerotation::Identity);
}
void ImGuiManager::UpdateTextures(const ImDrawData* draw_data)
{
for (ImTextureData* const tex : *draw_data->Textures)
@ -2228,7 +2216,8 @@ bool ImGuiManager::RenderAuxiliaryRenderWindow(AuxiliaryRenderWindowState* state
const GPUPresentResult pres = g_gpu_device->BeginPresent(state->swap_chain.get());
if (pres == GPUPresentResult::OK)
{
RenderDrawLists(ImGui::GetDrawData(), state->swap_chain.get());
RenderDrawLists(ImGui::GetDrawData(), state->swap_chain->GetWidth(), state->swap_chain->GetHeight(),
state->swap_chain->GetPreRotation());
g_gpu_device->EndPresent(state->swap_chain.get(), false);
}

@ -17,6 +17,7 @@ struct WindowInfo;
class GPUSwapChain;
class GPUTexture;
enum class GPUTextureFormat : u8;
enum class WindowInfoPrerotation : u8;
struct ImGuiContext;
struct ImDrawData;
@ -145,8 +146,8 @@ void NewFrame(u64 current_time);
void CreateDrawLists();
/// Renders ImGui screen elements. Call before EndPresent().
void RenderDrawLists(const ImDrawData* draw_data, GPUSwapChain* swap_chain);
void RenderDrawLists(const ImDrawData* draw_data, GPUTexture* texture);
void RenderDrawLists(const ImDrawData* draw_data, u32 window_width, u32 window_height,
WindowInfoPrerotation prerotation);
/// Renders any on-screen display elements.
void RenderOSDMessages();

Loading…
Cancel
Save