mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-30 07:13:18 +00:00
Renderer fixes (Splash + Aspect Ratio) (#2645)
* rewrite splash removed Splash class rewrite using imgui texture manager fix crashes & old validation error * handle games with abnormal aspect ratios
This commit is contained in:
parent
36927a7bbd
commit
5691046dcc
10 changed files with 66 additions and 222 deletions
|
@ -644,8 +644,6 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||||
src/core/file_format/playgo_chunk.h
|
src/core/file_format/playgo_chunk.h
|
||||||
src/core/file_format/trp.cpp
|
src/core/file_format/trp.cpp
|
||||||
src/core/file_format/trp.h
|
src/core/file_format/trp.h
|
||||||
src/core/file_format/splash.h
|
|
||||||
src/core/file_format/splash.cpp
|
|
||||||
src/core/file_sys/fs.cpp
|
src/core/file_sys/fs.cpp
|
||||||
src/core/file_sys/fs.h
|
src/core/file_sys/fs.h
|
||||||
src/core/loader.cpp
|
src/core/loader.cpp
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
@ -69,6 +70,8 @@ class ElfInfo {
|
||||||
u32 raw_firmware_ver = 0;
|
u32 raw_firmware_ver = 0;
|
||||||
PSFAttributes psf_attributes{};
|
PSFAttributes psf_attributes{};
|
||||||
|
|
||||||
|
std::filesystem::path splash_path{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr u32 FW_15 = 0x1500000;
|
static constexpr u32 FW_15 = 0x1500000;
|
||||||
static constexpr u32 FW_16 = 0x1600000;
|
static constexpr u32 FW_16 = 0x1600000;
|
||||||
|
@ -116,6 +119,10 @@ public:
|
||||||
ASSERT(initialized);
|
ASSERT(initialized);
|
||||||
return psf_attributes;
|
return psf_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const std::filesystem::path& GetSplashPath() const {
|
||||||
|
return splash_path;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
||||||
|
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
using namespace Core::Devtools;
|
using namespace ::Core::Devtools;
|
||||||
using L = Core::Devtools::Layer;
|
using L = ::Core::Devtools::Layer;
|
||||||
|
|
||||||
static bool show_simple_fps = false;
|
static bool show_simple_fps = false;
|
||||||
static bool visibility_toggled = false;
|
static bool visibility_toggled = false;
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
|
||||||
#include "common/io_file.h"
|
|
||||||
#include "common/stb.h"
|
|
||||||
#include "splash.h"
|
|
||||||
|
|
||||||
bool Splash::Open(const std::filesystem::path& filepath) {
|
|
||||||
ASSERT_MSG(filepath.extension().string() == ".png", "Unexpected file format passed");
|
|
||||||
|
|
||||||
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
|
|
||||||
if (!file.IsOpen()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> png_file{};
|
|
||||||
const auto png_size = file.GetSize();
|
|
||||||
png_file.resize(png_size);
|
|
||||||
file.Seek(0);
|
|
||||||
file.Read(png_file);
|
|
||||||
|
|
||||||
auto* img_mem = stbi_load_from_memory(png_file.data(), png_file.size(),
|
|
||||||
reinterpret_cast<int*>(&img_info.width),
|
|
||||||
reinterpret_cast<int*>(&img_info.height),
|
|
||||||
reinterpret_cast<int*>(&img_info.num_channels), 4);
|
|
||||||
if (!img_mem) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto img_size = img_info.GetSizeBytes();
|
|
||||||
img_data.resize(img_size);
|
|
||||||
std::memcpy(img_data.data(), img_mem, img_size);
|
|
||||||
stbi_image_free(img_mem);
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include "common/types.h"
|
|
||||||
|
|
||||||
class Splash {
|
|
||||||
public:
|
|
||||||
struct ImageInfo {
|
|
||||||
u32 width;
|
|
||||||
u32 height;
|
|
||||||
u32 num_channels;
|
|
||||||
|
|
||||||
u32 GetSizeBytes() const {
|
|
||||||
return width * height * 4; // we always forcing rgba8 for simplicity
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Splash() = default;
|
|
||||||
~Splash() = default;
|
|
||||||
|
|
||||||
bool Open(const std::filesystem::path& filepath);
|
|
||||||
[[nodiscard]] bool IsLoaded() const {
|
|
||||||
return img_data.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& GetImageData() const {
|
|
||||||
return img_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageInfo GetImageInfo() const {
|
|
||||||
return img_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ImageInfo img_info{};
|
|
||||||
std::vector<u8> img_data{};
|
|
||||||
};
|
|
|
@ -160,11 +160,8 @@ int VideoOutDriver::UnregisterBuffers(VideoOutPort* port, s32 attributeIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoOutDriver::Flip(const Request& req) {
|
void VideoOutDriver::Flip(const Request& req) {
|
||||||
// Whatever the game is rendering show splash if it is active
|
// Present the frame.
|
||||||
if (!presenter->ShowSplash(req.frame)) {
|
presenter->Present(req.frame);
|
||||||
// Present the frame.
|
|
||||||
presenter->Present(req.frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update flip status.
|
// Update flip status.
|
||||||
auto* port = req.port;
|
auto* port = req.port;
|
||||||
|
@ -201,9 +198,6 @@ void VideoOutDriver::Flip(const Request& req) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoOutDriver::DrawBlankFrame() {
|
void VideoOutDriver::DrawBlankFrame() {
|
||||||
if (presenter->ShowSplash(nullptr)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto empty_frame = presenter->PrepareBlankFrame(false);
|
const auto empty_frame = presenter->PrepareBlankFrame(false);
|
||||||
presenter->Present(empty_frame);
|
presenter->Present(empty_frame);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "core/file_format/psf.h"
|
#include "core/file_format/psf.h"
|
||||||
#include "core/file_format/splash.h"
|
|
||||||
#include "core/file_format/trp.h"
|
#include "core/file_format/trp.h"
|
||||||
#include "core/file_sys/fs.h"
|
#include "core/file_sys/fs.h"
|
||||||
#include "core/libraries/disc_map/disc_map.h"
|
#include "core/libraries/disc_map/disc_map.h"
|
||||||
|
@ -185,12 +184,7 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
|
||||||
|
|
||||||
const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png");
|
const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png");
|
||||||
if (std::filesystem::exists(pic1_path)) {
|
if (std::filesystem::exists(pic1_path)) {
|
||||||
auto* splash = Common::Singleton<Splash>::Instance();
|
game_info.splash_path = pic1_path;
|
||||||
if (!splash->IsLoaded()) {
|
|
||||||
if (!splash->Open(pic1_path)) {
|
|
||||||
LOG_ERROR(Loader, "Game splash: unable to open file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
game_info.initialized = true;
|
game_info.initialized = true;
|
||||||
|
|
|
@ -175,6 +175,7 @@ void WorkerLoop() {
|
||||||
|
|
||||||
auto texture = Vulkan::UploadTexture(pixels, vk::Format::eR8G8B8A8Unorm, width, height,
|
auto texture = Vulkan::UploadTexture(pixels, vk::Format::eR8G8B8A8Unorm, width, height,
|
||||||
width * height * 4 * sizeof(stbi_uc));
|
width * height * 4 * sizeof(stbi_uc));
|
||||||
|
stbi_image_free((void*)pixels);
|
||||||
|
|
||||||
core->upload_data = texture;
|
core->upload_data = texture;
|
||||||
core->width = width;
|
core->width = width;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
#include "core/debug_state.h"
|
#include "core/debug_state.h"
|
||||||
#include "core/devtools/layer.h"
|
#include "core/devtools/layer.h"
|
||||||
#include "core/file_format/splash.h"
|
|
||||||
#include "core/libraries/system/systemservice.h"
|
#include "core/libraries/system/systemservice.h"
|
||||||
#include "imgui/renderer/imgui_core.h"
|
#include "imgui/renderer/imgui_core.h"
|
||||||
#include "sdl_window.h"
|
#include "sdl_window.h"
|
||||||
|
@ -21,6 +20,8 @@
|
||||||
#include <vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "common/elf_info.h"
|
||||||
#include "imgui/renderer/imgui_impl_vulkan.h"
|
#include "imgui/renderer/imgui_impl_vulkan.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
@ -269,116 +270,10 @@ Frame* Presenter::PrepareLastFrame() {
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Presenter::ShowSplash(Frame* frame /*= nullptr*/) {
|
|
||||||
const auto* splash = Common::Singleton<Splash>::Instance();
|
|
||||||
if (splash->GetImageData().empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Libraries::SystemService::IsSplashVisible()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_scheduler.EndRendering();
|
|
||||||
const auto cmdbuf = draw_scheduler.CommandBuffer();
|
|
||||||
|
|
||||||
if (Config::getVkHostMarkersEnabled()) {
|
|
||||||
cmdbuf.beginDebugUtilsLabelEXT(vk::DebugUtilsLabelEXT{
|
|
||||||
.pLabelName = "ShowSplash",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!frame) {
|
|
||||||
if (!splash_img.has_value()) {
|
|
||||||
VideoCore::ImageInfo info{};
|
|
||||||
info.pixel_format = vk::Format::eR8G8B8A8Unorm;
|
|
||||||
info.type = vk::ImageType::e2D;
|
|
||||||
info.size =
|
|
||||||
VideoCore::Extent3D{splash->GetImageInfo().width, splash->GetImageInfo().height, 1};
|
|
||||||
info.pitch = splash->GetImageInfo().width;
|
|
||||||
info.guest_address = VAddr(splash->GetImageData().data());
|
|
||||||
info.guest_size = splash->GetImageData().size();
|
|
||||||
info.mips_layout.emplace_back(splash->GetImageData().size(),
|
|
||||||
splash->GetImageInfo().width,
|
|
||||||
splash->GetImageInfo().height, 0);
|
|
||||||
splash_img.emplace(instance, present_scheduler, info);
|
|
||||||
splash_img->flags &= ~VideoCore::GpuDirty;
|
|
||||||
texture_cache.RefreshImage(*splash_img);
|
|
||||||
|
|
||||||
splash_img->Transit(vk::ImageLayout::eTransferSrcOptimal,
|
|
||||||
vk::AccessFlagBits2::eTransferRead, {}, cmdbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
frame = GetRenderFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto frame_subresources = vk::ImageSubresourceRange{
|
|
||||||
.aspectMask = vk::ImageAspectFlagBits::eColor,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = 1,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto pre_barrier =
|
|
||||||
vk::ImageMemoryBarrier2{.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
|
||||||
.srcAccessMask = vk::AccessFlagBits2::eTransferRead,
|
|
||||||
.dstStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
|
||||||
.dstAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
|
||||||
.oldLayout = vk::ImageLayout::eUndefined,
|
|
||||||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
|
||||||
.image = frame->image,
|
|
||||||
.subresourceRange{frame_subresources}};
|
|
||||||
|
|
||||||
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
|
||||||
.imageMemoryBarrierCount = 1,
|
|
||||||
.pImageMemoryBarriers = &pre_barrier,
|
|
||||||
});
|
|
||||||
|
|
||||||
cmdbuf.blitImage(splash_img->image, vk::ImageLayout::eTransferSrcOptimal, frame->image,
|
|
||||||
vk::ImageLayout::eTransferDstOptimal,
|
|
||||||
MakeImageBlitFit(splash->GetImageInfo().width, splash->GetImageInfo().height,
|
|
||||||
frame->width, frame->height),
|
|
||||||
vk::Filter::eLinear);
|
|
||||||
|
|
||||||
const auto post_barrier =
|
|
||||||
vk::ImageMemoryBarrier2{.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
|
||||||
.srcAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
|
||||||
.dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput,
|
|
||||||
.dstAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite,
|
|
||||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
|
||||||
.newLayout = vk::ImageLayout::eGeneral,
|
|
||||||
.image = frame->image,
|
|
||||||
.subresourceRange{frame_subresources}};
|
|
||||||
|
|
||||||
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
|
||||||
.imageMemoryBarrierCount = 1,
|
|
||||||
.pImageMemoryBarriers = &post_barrier,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Config::getVkHostMarkersEnabled()) {
|
|
||||||
cmdbuf.endDebugUtilsLabelEXT();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush frame creation commands.
|
|
||||||
frame->ready_semaphore = draw_scheduler.GetMasterSemaphore()->Handle();
|
|
||||||
frame->ready_tick = draw_scheduler.CurrentTick();
|
|
||||||
SubmitInfo info{};
|
|
||||||
draw_scheduler.Flush(info);
|
|
||||||
|
|
||||||
Present(frame);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame* Presenter::PrepareFrameInternal(VideoCore::ImageId image_id, bool is_eop) {
|
Frame* Presenter::PrepareFrameInternal(VideoCore::ImageId image_id, bool is_eop) {
|
||||||
// Request a free presentation frame.
|
// Request a free presentation frame.
|
||||||
Frame* frame = GetRenderFrame();
|
Frame* frame = GetRenderFrame();
|
||||||
|
|
||||||
if (frame->width != expected_frame_width || frame->height != expected_frame_height ||
|
|
||||||
frame->is_hdr != swapchain.GetHDR()) {
|
|
||||||
RecreateFrame(frame, expected_frame_width, expected_frame_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// EOP flips are triggered from GPU thread so use the drawing scheduler to record
|
// EOP flips are triggered from GPU thread so use the drawing scheduler to record
|
||||||
// commands. Otherwise we are dealing with a CPU flip which could have arrived
|
// commands. Otherwise we are dealing with a CPU flip which could have arrived
|
||||||
// from any guest thread. Use a separate scheduler for that.
|
// from any guest thread. Use a separate scheduler for that.
|
||||||
|
@ -420,6 +315,11 @@ Frame* Presenter::PrepareFrameInternal(VideoCore::ImageId image_id, bool is_eop)
|
||||||
if (image_id != VideoCore::NULL_IMAGE_ID) {
|
if (image_id != VideoCore::NULL_IMAGE_ID) {
|
||||||
auto& image = texture_cache.GetImage(image_id);
|
auto& image = texture_cache.GetImage(image_id);
|
||||||
vk::Extent2D image_size = {image.info.size.width, image.info.size.height};
|
vk::Extent2D image_size = {image.info.size.width, image.info.size.height};
|
||||||
|
float ratio = (float)image_size.width / (float)image_size.height;
|
||||||
|
if (ratio != expected_ratio) {
|
||||||
|
expected_ratio = ratio;
|
||||||
|
}
|
||||||
|
|
||||||
image.Transit(vk::ImageLayout::eShaderReadOnlyOptimal, vk::AccessFlagBits2::eShaderRead, {},
|
image.Transit(vk::ImageLayout::eShaderReadOnlyOptimal, vk::AccessFlagBits2::eShaderRead, {},
|
||||||
cmdbuf);
|
cmdbuf);
|
||||||
|
|
||||||
|
@ -625,18 +525,43 @@ void Presenter::Present(Frame* frame, bool is_reusing_frame) {
|
||||||
ImGui::SetNextWindowDockID(dockId, ImGuiCond_Once);
|
ImGui::SetNextWindowDockID(dockId, ImGuiCond_Once);
|
||||||
ImGui::Begin("Display##game_display", nullptr, ImGuiWindowFlags_NoNav);
|
ImGui::Begin("Display##game_display", nullptr, ImGuiWindowFlags_NoNav);
|
||||||
|
|
||||||
|
auto game_texture = frame->imgui_texture;
|
||||||
|
auto game_width = frame->width;
|
||||||
|
auto game_height = frame->height;
|
||||||
|
|
||||||
|
if (Libraries::SystemService::IsSplashVisible()) { // draw splash
|
||||||
|
if (!splash_img.has_value()) {
|
||||||
|
splash_img.emplace();
|
||||||
|
auto splash_path = Common::ElfInfo::Instance().GetSplashPath();
|
||||||
|
if (!splash_path.empty()) {
|
||||||
|
splash_img = ImGui::RefCountedTexture::DecodePngFile(splash_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (auto& splash_image = this->splash_img.value()) {
|
||||||
|
auto [im_id, width, height] = splash_image.GetTexture();
|
||||||
|
game_texture = im_id;
|
||||||
|
game_width = width;
|
||||||
|
game_height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImVec2 contentArea = ImGui::GetContentRegionAvail();
|
ImVec2 contentArea = ImGui::GetContentRegionAvail();
|
||||||
const vk::Rect2D imgRect =
|
|
||||||
FitImage(frame->width, frame->height, (s32)contentArea.x, (s32)contentArea.y);
|
|
||||||
SetExpectedGameSize((s32)contentArea.x, (s32)contentArea.y);
|
SetExpectedGameSize((s32)contentArea.x, (s32)contentArea.y);
|
||||||
ImGui::SetCursorPos(ImGui::GetCursorStartPos() + ImVec2{
|
|
||||||
(float)imgRect.offset.x,
|
const auto imgRect =
|
||||||
(float)imgRect.offset.y,
|
FitImage(game_width, game_height, (s32)contentArea.x, (s32)contentArea.y);
|
||||||
});
|
ImVec2 offset{
|
||||||
ImGui::Image(frame->imgui_texture, {
|
static_cast<float>(imgRect.offset.x),
|
||||||
static_cast<float>(imgRect.extent.width),
|
static_cast<float>(imgRect.offset.y),
|
||||||
static_cast<float>(imgRect.extent.height),
|
};
|
||||||
});
|
ImVec2 size{
|
||||||
|
static_cast<float>(imgRect.extent.width),
|
||||||
|
static_cast<float>(imgRect.extent.height),
|
||||||
|
};
|
||||||
|
|
||||||
|
ImGui::SetCursorPos(ImGui::GetCursorStartPos() + offset);
|
||||||
|
ImGui::Image(game_texture, size);
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
ImGui::PopStyleVar(3);
|
ImGui::PopStyleVar(3);
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
@ -707,19 +632,23 @@ Frame* Presenter::GetRenderFrame() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (frame->width != expected_frame_width || frame->height != expected_frame_height ||
|
||||||
|
frame->is_hdr != swapchain.GetHDR()) {
|
||||||
|
RecreateFrame(frame, expected_frame_width, expected_frame_height);
|
||||||
|
}
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Presenter::SetExpectedGameSize(s32 width, s32 height) {
|
void Presenter::SetExpectedGameSize(s32 width, s32 height) {
|
||||||
constexpr float expectedRatio = 1920.0 / 1080.0f;
|
|
||||||
const float ratio = (float)width / (float)height;
|
const float ratio = (float)width / (float)height;
|
||||||
|
|
||||||
expected_frame_height = height;
|
expected_frame_height = height;
|
||||||
expected_frame_width = width;
|
expected_frame_width = width;
|
||||||
if (ratio > expectedRatio) {
|
if (ratio > expected_ratio) {
|
||||||
expected_frame_width = static_cast<s32>(height * expectedRatio);
|
expected_frame_width = static_cast<s32>(height * expected_ratio);
|
||||||
} else {
|
} else {
|
||||||
expected_frame_height = static_cast<s32>(width / expectedRatio);
|
expected_frame_height = static_cast<s32>(width / expected_ratio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
|
||||||
#include "imgui/imgui_config.h"
|
#include "imgui/imgui_config.h"
|
||||||
|
#include "imgui/imgui_texture.h"
|
||||||
#include "video_core/amdgpu/liverpool.h"
|
#include "video_core/amdgpu/liverpool.h"
|
||||||
#include "video_core/renderer_vulkan/host_passes/fsr_pass.h"
|
#include "video_core/renderer_vulkan/host_passes/fsr_pass.h"
|
||||||
#include "video_core/renderer_vulkan/host_passes/pp_pass.h"
|
#include "video_core/renderer_vulkan/host_passes/pp_pass.h"
|
||||||
|
@ -92,7 +93,6 @@ public:
|
||||||
}) != vo_buffers_addr.cend();
|
}) != vo_buffers_addr.cend();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShowSplash(Frame* frame = nullptr);
|
|
||||||
void Present(Frame* frame, bool is_reusing_frame = false);
|
void Present(Frame* frame, bool is_reusing_frame = false);
|
||||||
void RecreateFrame(Frame* frame, u32 width, u32 height);
|
void RecreateFrame(Frame* frame, u32 width, u32 height);
|
||||||
Frame* PrepareLastFrame();
|
Frame* PrepareLastFrame();
|
||||||
|
@ -125,6 +125,7 @@ private:
|
||||||
void SetExpectedGameSize(s32 width, s32 height);
|
void SetExpectedGameSize(s32 width, s32 height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
float expected_ratio{1920.0 / 1080.0f};
|
||||||
u32 expected_frame_width{1920};
|
u32 expected_frame_width{1920};
|
||||||
u32 expected_frame_height{1080};
|
u32 expected_frame_height{1080};
|
||||||
|
|
||||||
|
@ -148,7 +149,7 @@ private:
|
||||||
std::mutex free_mutex;
|
std::mutex free_mutex;
|
||||||
std::condition_variable free_cv;
|
std::condition_variable free_cv;
|
||||||
std::condition_variable_any frame_cv;
|
std::condition_variable_any frame_cv;
|
||||||
std::optional<VideoCore::Image> splash_img;
|
std::optional<ImGui::RefCountedTexture> splash_img;
|
||||||
std::vector<VAddr> vo_buffers_addr;
|
std::vector<VAddr> vo_buffers_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue