early-access version 2121
This commit is contained in:
parent
ac669c832d
commit
2c54215c89
7 changed files with 78 additions and 55 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 2118.
|
This is the source code for early-access 2121.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -170,7 +170,8 @@ public:
|
||||||
float GetAxis(int axis, float range, float offset) const {
|
float GetAxis(int axis, float range, float offset) const {
|
||||||
std::lock_guard lock{mutex};
|
std::lock_guard lock{mutex};
|
||||||
const float value = static_cast<float>(state.axes.at(axis)) / 32767.0f;
|
const float value = static_cast<float>(state.axes.at(axis)) / 32767.0f;
|
||||||
return (value + offset) / range;
|
const float offset_scale = (value + offset) > 0.0f ? 1.0f + offset : 1.0f - offset;
|
||||||
|
return (value + offset) / range / offset_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RumblePlay(u16 amp_low, u16 amp_high) {
|
bool RumblePlay(u16 amp_low, u16 amp_high) {
|
||||||
|
@ -789,8 +790,8 @@ public:
|
||||||
const std::string invert_y_value = params.Get("invert_y", "+");
|
const std::string invert_y_value = params.Get("invert_y", "+");
|
||||||
const bool invert_x = invert_x_value == "-";
|
const bool invert_x = invert_x_value == "-";
|
||||||
const bool invert_y = invert_y_value == "-";
|
const bool invert_y = invert_y_value == "-";
|
||||||
const float offset_x = params.Get("offset_x", 0.0f);
|
const float offset_x = std::clamp(params.Get("offset_x", 0.0f), -0.99f, 0.99f);
|
||||||
const float offset_y = params.Get("offset_y", 0.0f);
|
const float offset_y = std::clamp(params.Get("offset_y", 0.0f), -0.99f, 0.99f);
|
||||||
auto joystick = state.GetSDLJoystickByGUID(guid, port);
|
auto joystick = state.GetSDLJoystickByGUID(guid, port);
|
||||||
|
|
||||||
// This is necessary so accessing GetAxis with axis_x and axis_y won't crash
|
// This is necessary so accessing GetAxis with axis_x and axis_y won't crash
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
|
|
||||||
|
#include "common/settings.h"
|
||||||
#include "video_core/command_classes/codecs/h264.h"
|
#include "video_core/command_classes/codecs/h264.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
@ -96,7 +98,10 @@ const std::vector<u8>& H264::ComposeFrameHeader(const NvdecCommon::NvdecRegister
|
||||||
(context.h264_parameter_set.frame_mbs_only_flag ? 1 : 2);
|
(context.h264_parameter_set.frame_mbs_only_flag ? 1 : 2);
|
||||||
|
|
||||||
// TODO (ameerj): Where do we get this number, it seems to be particular for each stream
|
// TODO (ameerj): Where do we get this number, it seems to be particular for each stream
|
||||||
writer.WriteUe(6); // Max number of reference frames
|
const auto nvdec_decoding = Settings::values.nvdec_emulation.GetValue();
|
||||||
|
const bool uses_gpu_decoding = nvdec_decoding == Settings::NvdecEmulation::GPU;
|
||||||
|
const u32 max_num_ref_frames = uses_gpu_decoding ? 6u : 16u;
|
||||||
|
writer.WriteUe(max_num_ref_frames);
|
||||||
writer.WriteBit(false);
|
writer.WriteBit(false);
|
||||||
writer.WriteUe(context.h264_parameter_set.pic_width_in_mbs - 1);
|
writer.WriteUe(context.h264_parameter_set.pic_width_in_mbs - 1);
|
||||||
writer.WriteUe(pic_height - 1);
|
writer.WriteUe(pic_height - 1);
|
||||||
|
|
|
@ -32,7 +32,7 @@ enum class VideoPixelFormat : u64_le {
|
||||||
RGBA8 = 0x1f,
|
RGBA8 = 0x1f,
|
||||||
BGRA8 = 0x20,
|
BGRA8 = 0x20,
|
||||||
RGBX8 = 0x23,
|
RGBX8 = 0x23,
|
||||||
Yuv420 = 0x44,
|
YUV420 = 0x44,
|
||||||
};
|
};
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
@ -90,9 +90,8 @@ void Vic::Execute() {
|
||||||
if (static_cast<u64>(frame->width) != surface_width ||
|
if (static_cast<u64>(frame->width) != surface_width ||
|
||||||
static_cast<u64>(frame->height) != surface_height) {
|
static_cast<u64>(frame->height) != surface_height) {
|
||||||
// TODO: Properly support multiple video streams with differing frame dimensions
|
// TODO: Properly support multiple video streams with differing frame dimensions
|
||||||
LOG_WARNING(Debug, "Frame dimensions {}x{} do not match expected surface dimensions {}x{}",
|
LOG_WARNING(Service_NVDRV, "Frame dimensions {}x{} don't match surface dimensions {}x{}",
|
||||||
frame->width, frame->height, surface_width, surface_height);
|
frame->width, frame->height, surface_width, surface_height);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
switch (config.pixel_format) {
|
switch (config.pixel_format) {
|
||||||
case VideoPixelFormat::RGBA8:
|
case VideoPixelFormat::RGBA8:
|
||||||
|
@ -100,7 +99,7 @@ void Vic::Execute() {
|
||||||
case VideoPixelFormat::RGBX8:
|
case VideoPixelFormat::RGBX8:
|
||||||
WriteRGBFrame(frame, config);
|
WriteRGBFrame(frame, config);
|
||||||
break;
|
break;
|
||||||
case VideoPixelFormat::Yuv420:
|
case VideoPixelFormat::YUV420:
|
||||||
WriteYUVFrame(frame, config);
|
WriteYUVFrame(frame, config);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -135,21 +134,20 @@ void Vic::WriteRGBFrame(const AVFrame* frame, const VicConfig& config) {
|
||||||
scaler_height = frame->height;
|
scaler_height = frame->height;
|
||||||
converted_frame_buffer.reset();
|
converted_frame_buffer.reset();
|
||||||
}
|
}
|
||||||
// Get Converted frame
|
|
||||||
const u32 width = static_cast<u32>(frame->width);
|
|
||||||
const u32 height = static_cast<u32>(frame->height);
|
|
||||||
const std::size_t linear_size = width * height * 4;
|
|
||||||
|
|
||||||
// Only allocate frame_buffer once per stream, as the size is not expected to change
|
|
||||||
if (!converted_frame_buffer) {
|
if (!converted_frame_buffer) {
|
||||||
converted_frame_buffer = AVMallocPtr{static_cast<u8*>(av_malloc(linear_size)), av_free};
|
const size_t frame_size = frame->width * frame->height * 4;
|
||||||
|
converted_frame_buffer = AVMallocPtr{static_cast<u8*>(av_malloc(frame_size)), av_free};
|
||||||
}
|
}
|
||||||
const std::array<int, 4> converted_stride{frame->width * 4, frame->height * 4, 0, 0};
|
const std::array<int, 4> converted_stride{frame->width * 4, frame->height * 4, 0, 0};
|
||||||
u8* const converted_frame_buf_addr{converted_frame_buffer.get()};
|
u8* const converted_frame_buf_addr{converted_frame_buffer.get()};
|
||||||
|
|
||||||
sws_scale(scaler_ctx, frame->data, frame->linesize, 0, frame->height, &converted_frame_buf_addr,
|
sws_scale(scaler_ctx, frame->data, frame->linesize, 0, frame->height, &converted_frame_buf_addr,
|
||||||
converted_stride.data());
|
converted_stride.data());
|
||||||
|
|
||||||
|
// Use the minimum of surface/frame dimensions to avoid buffer overflow.
|
||||||
|
const u32 surface_width = static_cast<u32>(config.surface_width_minus1) + 1;
|
||||||
|
const u32 surface_height = static_cast<u32>(config.surface_height_minus1) + 1;
|
||||||
|
const u32 width = std::min(surface_width, static_cast<u32>(frame->width));
|
||||||
|
const u32 height = std::min(surface_height, static_cast<u32>(frame->height));
|
||||||
const u32 blk_kind = static_cast<u32>(config.block_linear_kind);
|
const u32 blk_kind = static_cast<u32>(config.block_linear_kind);
|
||||||
if (blk_kind != 0) {
|
if (blk_kind != 0) {
|
||||||
// swizzle pitch linear to block linear
|
// swizzle pitch linear to block linear
|
||||||
|
@ -157,11 +155,12 @@ void Vic::WriteRGBFrame(const AVFrame* frame, const VicConfig& config) {
|
||||||
const auto size = Texture::CalculateSize(true, 4, width, height, 1, block_height, 0);
|
const auto size = Texture::CalculateSize(true, 4, width, height, 1, block_height, 0);
|
||||||
luma_buffer.resize(size);
|
luma_buffer.resize(size);
|
||||||
Texture::SwizzleSubrect(width, height, width * 4, width, 4, luma_buffer.data(),
|
Texture::SwizzleSubrect(width, height, width * 4, width, 4, luma_buffer.data(),
|
||||||
converted_frame_buffer.get(), block_height, 0, 0);
|
converted_frame_buf_addr, block_height, 0, 0);
|
||||||
|
|
||||||
gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size);
|
gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size);
|
||||||
} else {
|
} else {
|
||||||
// send pitch linear frame
|
// send pitch linear frame
|
||||||
|
const size_t linear_size = width * height * 4;
|
||||||
gpu.MemoryManager().WriteBlock(output_surface_luma_address, converted_frame_buf_addr,
|
gpu.MemoryManager().WriteBlock(output_surface_luma_address, converted_frame_buf_addr,
|
||||||
linear_size);
|
linear_size);
|
||||||
}
|
}
|
||||||
|
@ -172,9 +171,10 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) {
|
||||||
|
|
||||||
const std::size_t surface_width = config.surface_width_minus1 + 1;
|
const std::size_t surface_width = config.surface_width_minus1 + 1;
|
||||||
const std::size_t surface_height = config.surface_height_minus1 + 1;
|
const std::size_t surface_height = config.surface_height_minus1 + 1;
|
||||||
|
const std::size_t aligned_width = (surface_width + 0xff) & ~0xffUL;
|
||||||
|
// Use the minimum of surface/frame dimensions to avoid buffer overflow.
|
||||||
const auto frame_width = std::min(surface_width, static_cast<size_t>(frame->width));
|
const auto frame_width = std::min(surface_width, static_cast<size_t>(frame->width));
|
||||||
const auto frame_height = std::min(surface_height, static_cast<size_t>(frame->height));
|
const auto frame_height = std::min(surface_height, static_cast<size_t>(frame->height));
|
||||||
const std::size_t aligned_width = (surface_width + 0xff) & ~0xffUL;
|
|
||||||
|
|
||||||
const auto stride = static_cast<size_t>(frame->linesize[0]);
|
const auto stride = static_cast<size_t>(frame->linesize[0]);
|
||||||
|
|
||||||
|
|
|
@ -1172,10 +1172,16 @@ void GMainWindow::ConnectMenuEvents() {
|
||||||
&GMainWindow::OnDisplayTitleBars);
|
&GMainWindow::OnDisplayTitleBars);
|
||||||
connect(ui.action_Show_Filter_Bar, &QAction::triggered, this, &GMainWindow::OnToggleFilterBar);
|
connect(ui.action_Show_Filter_Bar, &QAction::triggered, this, &GMainWindow::OnToggleFilterBar);
|
||||||
connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible);
|
connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible);
|
||||||
|
|
||||||
connect(ui.action_Reset_Window_Size_720, &QAction::triggered, this,
|
connect(ui.action_Reset_Window_Size_720, &QAction::triggered, this,
|
||||||
&GMainWindow::ResetWindowSize720);
|
&GMainWindow::ResetWindowSize720);
|
||||||
|
connect(ui.action_Reset_Window_Size_900, &QAction::triggered, this,
|
||||||
|
&GMainWindow::ResetWindowSize900);
|
||||||
connect(ui.action_Reset_Window_Size_1080, &QAction::triggered, this,
|
connect(ui.action_Reset_Window_Size_1080, &QAction::triggered, this,
|
||||||
&GMainWindow::ResetWindowSize1080);
|
&GMainWindow::ResetWindowSize1080);
|
||||||
|
ui.menu_Reset_Window_Size->addAction(ui.action_Reset_Window_Size_720);
|
||||||
|
ui.menu_Reset_Window_Size->addAction(ui.action_Reset_Window_Size_900);
|
||||||
|
ui.menu_Reset_Window_Size->addAction(ui.action_Reset_Window_Size_1080);
|
||||||
|
|
||||||
// Fullscreen
|
// Fullscreen
|
||||||
connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
|
connect(ui.action_Fullscreen, &QAction::triggered, this, &GMainWindow::ToggleFullscreen);
|
||||||
|
@ -2611,32 +2617,29 @@ void GMainWindow::ToggleWindowMode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::ResetWindowSize720() {
|
void GMainWindow::ResetWindowSize(u32 width, u32 height) {
|
||||||
const auto aspect_ratio = Layout::EmulationAspectRatio(
|
const auto aspect_ratio = Layout::EmulationAspectRatio(
|
||||||
static_cast<Layout::AspectRatio>(Settings::values.aspect_ratio.GetValue()),
|
static_cast<Layout::AspectRatio>(Settings::values.aspect_ratio.GetValue()),
|
||||||
static_cast<float>(Layout::ScreenUndocked::Height) / Layout::ScreenUndocked::Width);
|
static_cast<float>(height) / width);
|
||||||
if (!ui.action_Single_Window_Mode->isChecked()) {
|
if (!ui.action_Single_Window_Mode->isChecked()) {
|
||||||
render_window->resize(Layout::ScreenUndocked::Height / aspect_ratio,
|
render_window->resize(height / aspect_ratio, height);
|
||||||
Layout::ScreenUndocked::Height);
|
|
||||||
} else {
|
} else {
|
||||||
resize(Layout::ScreenUndocked::Height / aspect_ratio,
|
const bool show_status_bar = ui.action_Show_Status_Bar->isChecked();
|
||||||
Layout::ScreenUndocked::Height + menuBar()->height() +
|
const auto status_bar_height = show_status_bar ? statusBar()->height() : 0;
|
||||||
(ui.action_Show_Status_Bar->isChecked() ? statusBar()->height() : 0));
|
resize(height / aspect_ratio, height + menuBar()->height() + status_bar_height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GMainWindow::ResetWindowSize720() {
|
||||||
|
ResetWindowSize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::ResetWindowSize900() {
|
||||||
|
ResetWindowSize(1600U, 900U);
|
||||||
|
}
|
||||||
|
|
||||||
void GMainWindow::ResetWindowSize1080() {
|
void GMainWindow::ResetWindowSize1080() {
|
||||||
const auto aspect_ratio = Layout::EmulationAspectRatio(
|
ResetWindowSize(Layout::ScreenDocked::Width, Layout::ScreenDocked::Height);
|
||||||
static_cast<Layout::AspectRatio>(Settings::values.aspect_ratio.GetValue()),
|
|
||||||
static_cast<float>(Layout::ScreenDocked::Height) / Layout::ScreenDocked::Width);
|
|
||||||
if (!ui.action_Single_Window_Mode->isChecked()) {
|
|
||||||
render_window->resize(Layout::ScreenDocked::Height / aspect_ratio,
|
|
||||||
Layout::ScreenDocked::Height);
|
|
||||||
} else {
|
|
||||||
resize(Layout::ScreenDocked::Height / aspect_ratio,
|
|
||||||
Layout::ScreenDocked::Height + menuBar()->height() +
|
|
||||||
(ui.action_Show_Status_Bar->isChecked() ? statusBar()->height() : 0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnConfigure() {
|
void GMainWindow::OnConfigure() {
|
||||||
|
|
|
@ -272,7 +272,9 @@ private slots:
|
||||||
void ShowFullscreen();
|
void ShowFullscreen();
|
||||||
void HideFullscreen();
|
void HideFullscreen();
|
||||||
void ToggleWindowMode();
|
void ToggleWindowMode();
|
||||||
|
void ResetWindowSize(u32 width, u32 height);
|
||||||
void ResetWindowSize720();
|
void ResetWindowSize720();
|
||||||
|
void ResetWindowSize900();
|
||||||
void ResetWindowSize1080();
|
void ResetWindowSize1080();
|
||||||
void OnCaptureScreenshot();
|
void OnCaptureScreenshot();
|
||||||
void OnCoreError(Core::System::ResultStatus, std::string);
|
void OnCoreError(Core::System::ResultStatus, std::string);
|
||||||
|
|
|
@ -78,6 +78,35 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>&View</string>
|
<string>&View</string>
|
||||||
</property>
|
</property>
|
||||||
|
<widget class="QMenu" name="menu_Reset_Window_Size">
|
||||||
|
<property name="title">
|
||||||
|
<string>&Reset Window Size</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<action name="action_Reset_Window_Size_720">
|
||||||
|
<property name="text">
|
||||||
|
<string>Reset Window Size to &720p</string>
|
||||||
|
</property>
|
||||||
|
<property name="iconText">
|
||||||
|
<string>Reset Window Size to 720p</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_Reset_Window_Size_900">
|
||||||
|
<property name="text">
|
||||||
|
<string>Reset Window Size to &900p</string>
|
||||||
|
</property>
|
||||||
|
<property name="iconText">
|
||||||
|
<string>Reset Window Size to 900p</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_Reset_Window_Size_1080">
|
||||||
|
<property name="text">
|
||||||
|
<string>Reset Window Size to &1080p</string>
|
||||||
|
</property>
|
||||||
|
<property name="iconText">
|
||||||
|
<string>Reset Window Size to 1080p</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<widget class="QMenu" name="menu_View_Debugging">
|
<widget class="QMenu" name="menu_View_Debugging">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>&Debugging</string>
|
<string>&Debugging</string>
|
||||||
|
@ -88,9 +117,8 @@
|
||||||
<addaction name="action_Display_Dock_Widget_Headers"/>
|
<addaction name="action_Display_Dock_Widget_Headers"/>
|
||||||
<addaction name="action_Show_Filter_Bar"/>
|
<addaction name="action_Show_Filter_Bar"/>
|
||||||
<addaction name="action_Show_Status_Bar"/>
|
<addaction name="action_Show_Status_Bar"/>
|
||||||
<addaction name="action_Reset_Window_Size_720"/>
|
|
||||||
<addaction name="action_Reset_Window_Size_1080"/>
|
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
|
<addaction name="menu_Reset_Window_Size"/>
|
||||||
<addaction name="menu_View_Debugging"/>
|
<addaction name="menu_View_Debugging"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menu_Tools">
|
<widget class="QMenu" name="menu_Tools">
|
||||||
|
@ -216,22 +244,6 @@
|
||||||
<string>Show Status Bar</string>
|
<string>Show Status Bar</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_Reset_Window_Size_720">
|
|
||||||
<property name="text">
|
|
||||||
<string>Reset Window Size to &720p</string>
|
|
||||||
</property>
|
|
||||||
<property name="iconText">
|
|
||||||
<string>Reset Window Size to 720p</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="action_Reset_Window_Size_1080">
|
|
||||||
<property name="text">
|
|
||||||
<string>Reset Window Size to &1080p</string>
|
|
||||||
</property>
|
|
||||||
<property name="iconText">
|
|
||||||
<string>Reset Window Size to 1080p</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="action_Fullscreen">
|
<action name="action_Fullscreen">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|
Loading…
Reference in a new issue