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) 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, GPUTexture::Type::RenderTarget, swap_chain->GetFormat(), GPUTexture::Flags::None,
false)) false))
{ {
ERROR_LOG("Failed to allocate {}x{} texture for transition, cancelling.", swap_chain->GetWidth(), ERROR_LOG("Failed to allocate {}x{} texture for transition, cancelling.", swap_chain_width, swap_chain_height);
swap_chain->GetHeight());
s_state.transition_state = TransitionState::Inactive; s_state.transition_state = TransitionState::Inactive;
return nullptr; 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()); g_gpu_device->SetViewportAndScissor(0, 0, swap_chain->GetPostRotatedWidth(), swap_chain->GetPostRotatedHeight());
const GSVector2i size = swap_chain->GetSizeVec(); 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) : 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); GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f);
VideoPresenter::DrawScreenQuad(GSVector4i::loadh(size), uv_rect, size, postrotated_size, DisplayRotation::Normal, VideoPresenter::DrawScreenQuad(GSVector4i::loadh(size), uv_rect, size, size, DisplayRotation::Normal,
swap_chain->GetPreRotation(), uniforms, sizeof(uniforms)); WindowInfoPrerotation::Identity, uniforms, sizeof(uniforms));
} }
void FullscreenUI::UpdateTransitionState() void FullscreenUI::UpdateTransitionState()
@ -1493,7 +1493,7 @@ void FullscreenUI::InvalidateBlurBackground()
s_state.blur_valid = false; s_state.blur_valid = false;
} }
GPUTexture* FullscreenUI::GetBlurRenderTexture() GPUTexture* FullscreenUI::GetBlurRenderTexture(GPUSwapChain* const swap_chain)
{ {
if (!s_state.blur_active) if (!s_state.blur_active)
return nullptr; return nullptr;
@ -1501,10 +1501,6 @@ GPUTexture* FullscreenUI::GetBlurRenderTexture()
// clear for next frame // clear for next frame
s_state.blur_active = false; 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_width = swap_chain->GetPostRotatedWidth();
const u32 swap_chain_height = swap_chain->GetPostRotatedHeight(); const u32 swap_chain_height = swap_chain->GetPostRotatedHeight();
u32 blur_width, blur_height; u32 blur_width, blur_height;
@ -1542,7 +1538,7 @@ GPUTexture* FullscreenUI::GetBlurRenderTexture()
} }
s_state.blur_texture_scale = 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; s_state.blur_valid = false;
} }
@ -1551,7 +1547,7 @@ GPUTexture* FullscreenUI::GetBlurRenderTexture()
return s_state.blur_valid ? nullptr : s_state.blur_source_texture.get(); 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_source_texture && s_state.blur_source_texture.get() == blur_render_texture);
DebugAssert(s_state.blur_intermediate_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 source_size_vec = s_state.blur_source_texture->GetSizeVec();
const GSVector2i size_vec = s_state.blur_output_texture->GetSizeVec(); const GSVector2i size_vec = s_state.blur_output_texture->GetSizeVec();
const GSVector4i viewport = GSVector4i::loadh(size_vec); 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 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); 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(); blur_render_texture->MakeReadyForSampling();
g_gpu_device->SetViewport(viewport); 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.Textures = &io.Fonts->TexList;
draw_data.AddDrawList(&draw_list); draw_data.AddDrawList(&draw_list);
GPUSwapChain* const swap_chain = g_gpu_device->GetMainSwapChain();
if (s_state.blur_active && !s_state.blur_valid) if (s_state.blur_active && !s_state.blur_valid)
{ {
GPUTexture* const blur_target = GetBlurRenderTexture(); GPUTexture* const blur_target = GetBlurRenderTexture(swap_chain);
if (blur_target) if (blur_target)
{ {
VideoPresenter::RenderDisplay(blur_target, blur_target->GetSizeVec(), false, true); VideoPresenter::RenderDisplay(blur_target, blur_target->GetSizeVec(), swap_chain->GetPostRotatedSizeVec(),
RenderBlur(blur_target); 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) 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); g_gpu_device->EndPresent(swap_chain, false);
} }
} }

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

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

@ -74,7 +74,8 @@ void ThrottlePresentation();
bool PresentFrame(GPUBackend* backend, u64 present_time); 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. /// 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. /// Returns a list of border overlay presets.
std::vector<std::string> EnumerateBorderOverlayPresets(); std::vector<std::string> EnumerateBorderOverlayPresets();

@ -97,8 +97,6 @@ static bool LoadFontData(Error* error);
static void ReloadFontDataIfActive(); static void ReloadFontDataIfActive();
static bool CreateFontAtlas(Error* error); static bool CreateFontAtlas(Error* error);
static bool CompilePipelines(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 UpdateTextures(const ImDrawData* draw_data);
static void DestroyTextures(bool recycle); static void DestroyTextures(bool recycle);
static void SetCommonIOOptions(ImGuiIO& io, ImGuiPlatformIO& pio); 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) void ImGuiManager::UpdateTextures(const ImDrawData* draw_data)
{ {
for (ImTextureData* const tex : *draw_data->Textures) 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()); const GPUPresentResult pres = g_gpu_device->BeginPresent(state->swap_chain.get());
if (pres == GPUPresentResult::OK) 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); g_gpu_device->EndPresent(state->swap_chain.get(), false);
} }

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

Loading…
Cancel
Save