mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-28 05:59:24 -04:00
Compare commits
9 commits
39ace80a48
...
d0a50eeb14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0a50eeb14 | ||
|
|
ccc59f8417 | ||
|
|
1035238473 | ||
|
|
300b68e18d | ||
|
|
32cf070174 | ||
|
|
cfdac4d3b9 | ||
|
|
7bf5442a1c | ||
|
|
1f8c5418ac | ||
|
|
cb0d14258b |
43 changed files with 5252 additions and 340 deletions
|
|
@ -48,6 +48,8 @@ foreach(KEY IN ITEMS
|
|||
"turbo_limit"
|
||||
"texture_filter"
|
||||
"antialiasing_filter"
|
||||
"output_scaling"
|
||||
"fsr_sharpness"
|
||||
"texture_sampling"
|
||||
"delay_game_render_thread_us"
|
||||
"simulate_3ds_gpu_timings"
|
||||
|
|
|
|||
|
|
@ -726,6 +726,8 @@ void QtConfig::ReadRendererValues() {
|
|||
|
||||
ReadGlobalSetting(Settings::values.texture_filter);
|
||||
ReadGlobalSetting(Settings::values.antialiasing_filter);
|
||||
ReadGlobalSetting(Settings::values.output_scaling);
|
||||
ReadGlobalSetting(Settings::values.fsr_sharpness);
|
||||
ReadGlobalSetting(Settings::values.texture_sampling);
|
||||
|
||||
ReadGlobalSetting(Settings::values.delay_game_render_thread_us);
|
||||
|
|
@ -1276,6 +1278,8 @@ void QtConfig::SaveRendererValues() {
|
|||
|
||||
WriteGlobalSetting(Settings::values.texture_filter);
|
||||
WriteGlobalSetting(Settings::values.antialiasing_filter);
|
||||
WriteGlobalSetting(Settings::values.output_scaling);
|
||||
WriteGlobalSetting(Settings::values.fsr_sharpness);
|
||||
WriteGlobalSetting(Settings::values.texture_sampling);
|
||||
|
||||
WriteGlobalSetting(Settings::values.delay_game_render_thread_us);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ ConfigureEnhancements::ConfigureEnhancements(QWidget* parent)
|
|||
updateShaders(static_cast<Settings::StereoRenderOption>(currentIndex));
|
||||
});
|
||||
|
||||
connect(ui->fsr_sharpness_slider, &QSlider::valueChanged, this,
|
||||
&ConfigureEnhancements::SetFSRSharpnessIndicatorText);
|
||||
ui->toggle_preload_textures->setEnabled(ui->toggle_custom_textures->isChecked());
|
||||
ui->toggle_async_custom_loading->setEnabled(ui->toggle_custom_textures->isChecked());
|
||||
connect(ui->toggle_custom_textures, &QCheckBox::toggled, this, [this] {
|
||||
|
|
@ -35,12 +37,18 @@ ConfigureEnhancements::ConfigureEnhancements(QWidget* parent)
|
|||
if (!ui->toggle_preload_textures->isEnabled())
|
||||
ui->toggle_preload_textures->setChecked(false);
|
||||
});
|
||||
connect(ui->output_scaling_combobox, &QComboBox::currentIndexChanged, this, &ConfigureEnhancements::SetFSRSharpnessEnabled);
|
||||
}
|
||||
|
||||
ConfigureEnhancements::~ConfigureEnhancements() = default;
|
||||
|
||||
void ConfigureEnhancements::SetConfiguration() {
|
||||
|
||||
const s32 sharpness =
|
||||
static_cast<s32>(Settings::values.fsr_sharpness.GetValue());
|
||||
ui->fsr_sharpness_slider->setValue(sharpness);
|
||||
SetFSRSharpnessIndicatorText(ui->fsr_sharpness_slider->sliderPosition());
|
||||
|
||||
if (!Settings::IsConfiguringGlobal()) {
|
||||
ConfigurationShared::SetPerGameSetting(ui->resolution_factor_combobox,
|
||||
&Settings::values.resolution_factor);
|
||||
|
|
@ -52,6 +60,10 @@ void ConfigureEnhancements::SetConfiguration() {
|
|||
&Settings::values.antialiasing_filter);
|
||||
ConfigurationShared::SetHighlight(ui->widget_antialiasing_filter,
|
||||
!Settings::values.antialiasing_filter.UsingGlobal());
|
||||
ConfigurationShared::SetPerGameSetting(ui->output_scaling_combobox,
|
||||
&Settings::values.output_scaling);
|
||||
ConfigurationShared::SetHighlight(ui->widget_output_scaling,
|
||||
!Settings::values.output_scaling.UsingGlobal());
|
||||
} else {
|
||||
ui->resolution_factor_combobox->setCurrentIndex(
|
||||
Settings::values.resolution_factor.GetValue());
|
||||
|
|
@ -59,8 +71,10 @@ void ConfigureEnhancements::SetConfiguration() {
|
|||
static_cast<int>(Settings::values.texture_filter.GetValue()));
|
||||
ui->antialiasing_filter_combobox->setCurrentIndex(
|
||||
static_cast<int>(Settings::values.antialiasing_filter.GetValue()));
|
||||
ui->output_scaling_combobox->setCurrentIndex(
|
||||
static_cast<int>(Settings::values.output_scaling.GetValue()));
|
||||
}
|
||||
|
||||
ui->fsr_sharpness_slider->setEnabled(ui->output_scaling_combobox->currentIndex() == 3);
|
||||
ui->render_3d_combobox->setCurrentIndex(
|
||||
static_cast<int>(Settings::values.render_3d.GetValue()));
|
||||
ui->swap_eyes_3d->setChecked(Settings::values.swap_eyes_3d.GetValue());
|
||||
|
|
@ -68,7 +82,6 @@ void ConfigureEnhancements::SetConfiguration() {
|
|||
ui->mono_rendering_eye->setCurrentIndex(
|
||||
static_cast<int>(Settings::values.mono_render_option.GetValue()));
|
||||
updateShaders(Settings::values.render_3d.GetValue());
|
||||
ui->toggle_linear_filter->setChecked(Settings::values.filter_mode.GetValue());
|
||||
ui->use_integer_scaling->setChecked(Settings::values.use_integer_scaling.GetValue());
|
||||
ui->toggle_dump_textures->setChecked(Settings::values.dump_textures.GetValue());
|
||||
ui->toggle_custom_textures->setChecked(Settings::values.custom_textures.GetValue());
|
||||
|
|
@ -77,6 +90,13 @@ void ConfigureEnhancements::SetConfiguration() {
|
|||
ui->disable_right_eye_render->setChecked(Settings::values.disable_right_eye_render.GetValue());
|
||||
}
|
||||
|
||||
void ConfigureEnhancements::SetFSRSharpnessIndicatorText(int percentage) {
|
||||
ui->fsr_sharpness_indicator->setText(tr("%1%", "FSR Sharpness (e.g. 50%)").arg(percentage));
|
||||
}
|
||||
|
||||
void ConfigureEnhancements::SetFSRSharpnessEnabled(int output) {
|
||||
ui->fsr_sharpness_slider->setEnabled(output == 3);
|
||||
}
|
||||
void ConfigureEnhancements::updateShaders(Settings::StereoRenderOption stereo_option) {
|
||||
ui->shader_combobox->clear();
|
||||
ui->shader_combobox->setEnabled(true);
|
||||
|
|
@ -130,16 +150,17 @@ void ConfigureEnhancements::ApplyConfiguration() {
|
|||
Settings::values.pp_shader_name =
|
||||
ui->shader_combobox->itemText(ui->shader_combobox->currentIndex()).toStdString();
|
||||
}
|
||||
Settings::values.fsr_sharpness = ui->fsr_sharpness_slider->sliderPosition();
|
||||
Settings::values.disable_right_eye_render = ui->disable_right_eye_render->isChecked();
|
||||
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.filter_mode,
|
||||
ui->toggle_linear_filter, linear_filter);
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_integer_scaling,
|
||||
ui->use_integer_scaling, use_integer_scaling);
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.texture_filter,
|
||||
ui->texture_filter_combobox);
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.antialiasing_filter,
|
||||
ui->antialiasing_filter_combobox);
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.output_scaling,
|
||||
ui->output_scaling_combobox);
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.dump_textures,
|
||||
ui->toggle_dump_textures, dump_textures);
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.custom_textures,
|
||||
|
|
@ -159,7 +180,7 @@ void ConfigureEnhancements::SetupPerGameUI() {
|
|||
ui->widget_resolution->setEnabled(Settings::values.resolution_factor.UsingGlobal());
|
||||
ui->widget_texture_filter->setEnabled(Settings::values.texture_filter.UsingGlobal());
|
||||
ui->widget_antialiasing_filter->setEnabled(Settings::values.antialiasing_filter.UsingGlobal());
|
||||
ui->toggle_linear_filter->setEnabled(Settings::values.filter_mode.UsingGlobal());
|
||||
ui->widget_output_scaling->setEnabled(Settings::values.output_scaling.UsingGlobal());
|
||||
ui->use_integer_scaling->setEnabled(Settings::values.use_integer_scaling.UsingGlobal());
|
||||
ui->toggle_dump_textures->setEnabled(Settings::values.dump_textures.UsingGlobal());
|
||||
ui->toggle_custom_textures->setEnabled(Settings::values.custom_textures.UsingGlobal());
|
||||
|
|
@ -177,8 +198,6 @@ void ConfigureEnhancements::SetupPerGameUI() {
|
|||
|
||||
ui->widget_shader->setVisible(false);
|
||||
|
||||
ConfigurationShared::SetColoredTristate(ui->toggle_linear_filter, Settings::values.filter_mode,
|
||||
linear_filter);
|
||||
ConfigurationShared::SetColoredTristate(
|
||||
ui->use_integer_scaling, Settings::values.use_integer_scaling, use_integer_scaling);
|
||||
ConfigurationShared::SetColoredTristate(ui->toggle_dump_textures,
|
||||
|
|
@ -205,4 +224,8 @@ void ConfigureEnhancements::SetupPerGameUI() {
|
|||
ConfigurationShared::SetColoredComboBox(
|
||||
ui->antialiasing_filter_combobox, ui->widget_antialiasing_filter,
|
||||
static_cast<int>(Settings::values.antialiasing_filter.GetValue(true)));
|
||||
|
||||
ConfigurationShared::SetColoredComboBox(
|
||||
ui->output_scaling_combobox, ui->widget_output_scaling,
|
||||
static_cast<int>(Settings::values.output_scaling.GetValue(true)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ public:
|
|||
private:
|
||||
void updateShaders(Settings::StereoRenderOption stereo_option);
|
||||
void updateTextureFilter(int index);
|
||||
|
||||
void SetFSRSharpnessIndicatorText(int percentage);
|
||||
void SetFSRSharpnessEnabled(int output);
|
||||
std::unique_ptr<Ui::ConfigureEnhancements> ui;
|
||||
ConfigurationShared::CheckState linear_filter;
|
||||
ConfigurationShared::CheckState use_integer_scaling;
|
||||
|
|
|
|||
|
|
@ -121,10 +121,184 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="toggle_linear_filter">
|
||||
<property name="text">
|
||||
<string>Enable Linear Filtering</string>
|
||||
<widget class="QWidget" name="widget_output_scaling" native="true">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="output_scaling_label">
|
||||
<property name="text">
|
||||
<string>Output Scaling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="output_scaling_combobox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Nearest</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bilinear</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Adaptive</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>AMD FidelityFX Super Resolution 1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sharp Bilinear</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_fsr_sharpness" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_fsr_sharpness_1" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_17">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="fsr_sharpness_label">
|
||||
<property name="text">
|
||||
<string>FSR Sharpness</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_fsr_sharpness_2" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_18">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSlider" name="fsr_sharpness_slider">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="fsr_sharpness_indicator">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0 %</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
|
@ -457,7 +631,6 @@
|
|||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>resolution_factor_combobox</tabstop>
|
||||
<tabstop>toggle_linear_filter</tabstop>
|
||||
<tabstop>shader_combobox</tabstop>
|
||||
<tabstop>texture_filter_combobox</tabstop>
|
||||
<tabstop>antialiasing_filter_combobox</tabstop>
|
||||
|
|
|
|||
|
|
@ -69,6 +69,23 @@ std::string_view GetAntialiasingFilterName(AntiAliasingFilter filter) {
|
|||
return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
std::string_view GetOutputScalingName(OutputScaling scaling) {
|
||||
switch (scaling) {
|
||||
case OutputScaling::Nearest:
|
||||
return "Nearest";
|
||||
case OutputScaling::Bilinear:
|
||||
return "Bilinear";
|
||||
case OutputScaling::Adaptive:
|
||||
return "Adaptive";
|
||||
case OutputScaling::FSR:
|
||||
return "AMD FidelityFX Super Resolution 1";
|
||||
case OutputScaling::SharpBilinear:
|
||||
return "Sharp Bilinear";
|
||||
default:
|
||||
return "Invalid";
|
||||
}
|
||||
}
|
||||
std::string_view GetTextureSamplingName(TextureSampling sampling) {
|
||||
switch (sampling) {
|
||||
case TextureSampling::GameControlled:
|
||||
|
|
@ -116,6 +133,7 @@ void LogSettings() {
|
|||
log_setting("Renderer_FilterMode", values.filter_mode.GetValue());
|
||||
log_setting("Renderer_TextureFilter", GetTextureFilterName(values.texture_filter.GetValue()));
|
||||
log_setting("Renderer_AntialiasingFilter", GetAntialiasingFilterName(values.antialiasing_filter.GetValue()));
|
||||
log_setting("Renderer_OutputScaling", GetOutputScalingName(values.output_scaling.GetValue()));
|
||||
log_setting("Renderer_TextureSampling",
|
||||
GetTextureSamplingName(values.texture_sampling.GetValue()));
|
||||
log_setting("Renderer_DelayGameRenderThreasUs", values.delay_game_render_thread_us.GetValue());
|
||||
|
|
@ -230,6 +248,8 @@ void RestoreGlobalState(bool is_powered_on) {
|
|||
values.frame_limit.SetGlobal(true);
|
||||
values.texture_filter.SetGlobal(true);
|
||||
values.antialiasing_filter.SetGlobal(true);
|
||||
values.output_scaling.SetGlobal(true);
|
||||
values.fsr_sharpness.SetGlobal(true);
|
||||
values.texture_sampling.SetGlobal(true);
|
||||
values.delay_game_render_thread_us.SetGlobal(true);
|
||||
values.simulate_3ds_gpu_timings.SetGlobal(true);
|
||||
|
|
|
|||
|
|
@ -118,6 +118,14 @@ enum class AntiAliasingFilter : u32 {
|
|||
SMAA = 2,
|
||||
};
|
||||
|
||||
enum class OutputScaling : u32 {
|
||||
Nearest = 0,
|
||||
Bilinear = 1,
|
||||
Adaptive = 2,
|
||||
FSR = 3,
|
||||
SharpBilinear = 4,
|
||||
};
|
||||
|
||||
enum class TextureSampling : u32 {
|
||||
GameControlled = 0,
|
||||
NearestNeighbor = 1,
|
||||
|
|
@ -546,6 +554,8 @@ struct Values {
|
|||
SwitchableSetting<double, true> turbo_limit{200, 0, 1000, Keys::turbo_limit};
|
||||
SwitchableSetting<TextureFilter> texture_filter{TextureFilter::NoFilter, Keys::texture_filter};
|
||||
SwitchableSetting<AntiAliasingFilter> antialiasing_filter{AntiAliasingFilter::None, Keys::antialiasing_filter};
|
||||
SwitchableSetting<OutputScaling> output_scaling{OutputScaling::Adaptive, Keys::output_scaling};
|
||||
SwitchableSetting<int, true> fsr_sharpness{50, 0, 100, Keys::fsr_sharpness};
|
||||
SwitchableSetting<TextureSampling> texture_sampling{TextureSampling::GameControlled,
|
||||
Keys::texture_sampling};
|
||||
SwitchableSetting<u16, true> delay_game_render_thread_us{0, 0, 65000,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,17 @@ set(SHADER_FILES
|
|||
scaling/opengl_area_sampling.vert
|
||||
scaling/vulkan_area_sampling.frag
|
||||
scaling/vulkan_area_sampling.vert
|
||||
scaling/FSR/OpenGL/opengl_fsr_pass0.vert
|
||||
scaling/FSR/OpenGL/opengl_fsr_pass0_part1.frag
|
||||
scaling/FSR/OpenGL/opengl_fsr_pass0_part2.frag
|
||||
scaling/FSR/OpenGL/opengl_fsr_pass1.vert
|
||||
scaling/FSR/OpenGL/opengl_fsr_pass1_part1.frag
|
||||
scaling/FSR/OpenGL/opengl_fsr_pass1_part2.frag
|
||||
scaling/FSR/OpenGL/opengl_fsr_pass1_part3.frag
|
||||
scaling/FSR/ffx_a.h
|
||||
scaling/FSR/ffx_fsr1.h
|
||||
scaling/SharpBilinear/OpenGL/opengl_sharpbilinear.vert
|
||||
scaling/SharpBilinear/OpenGL/opengl_sharpbilinear.frag
|
||||
full_screen_triangle.vert
|
||||
opengl_present.frag
|
||||
opengl_present.vert
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ FXAA_SUBPIX_CAP - Insures fine detail is not completely removed.
|
|||
|
||||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
|
|
@ -64,14 +64,8 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
|
||||
/*
|
||||
screen_textures[0] = color_texture
|
||||
*/
|
||||
#ifndef FXAA_PRESET
|
||||
#define FXAA_PRESET 5
|
||||
#endif
|
||||
|
|
@ -263,7 +257,7 @@ vec3 sRGBToLinear(vec3 c) {
|
|||
|
||||
void main()
|
||||
{
|
||||
vec4 pixel = vec4(FxaaPixelShader(frag_tex_coord, screen_textures[0], vec2(i_resolution.z, i_resolution.w)), 1.0) * 1.0;
|
||||
vec4 pixel = vec4(FxaaPixelShader(frag_tex_coord, color_texture, vec2(i_resolution.z, i_resolution.w)), 1.0) * 1.0;
|
||||
if (convert_colors == 1){
|
||||
pixel = vec4(sRGBToLinear(pixel.rgb), pixel.a);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,18 +10,12 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec2 vert_position;
|
||||
layout(location = 1) in vec2 vert_tex_coord;
|
||||
layout(location = 0) out vec2 frag_tex_coord;
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
/*
|
||||
screen_textures[0] = color_texture
|
||||
*/
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
void main() {
|
||||
if (SMAA_EDT == 0.0) {
|
||||
color = vec4(SMAALumaEdgeDetectionPS(frag_tex_coord, offset, screen_textures[0]), 0.0, 0.0);
|
||||
color = vec4(SMAALumaEdgeDetectionPS(frag_tex_coord, offset, color_texture), 0.0, 0.0);
|
||||
} else if (SMAA_EDT <= 1.0) {
|
||||
color = vec4(SMAAColorEdgeDetectionPS(frag_tex_coord, offset, screen_textures[0]), 0.0, 0.0);
|
||||
color = vec4(SMAAColorEdgeDetectionPS(frag_tex_coord, offset, color_texture), 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
|
|
@ -27,9 +24,7 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 1) in vec4 offset[3];
|
||||
layout(location = 0) out vec4 color;
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
/*
|
||||
screen_textures[0] = color_texture
|
||||
*/
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
#define SMAA_INCLUDE_VS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -13,9 +13,6 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
void main() {
|
||||
vec4 subsampleIndices = vec4(0.0);
|
||||
color = SMAABlendingWeightCalculationPS(frag_tex_coord, pixcoord, offset, screen_textures[0], screen_textures[1], screen_textures[2], subsampleIndices);
|
||||
color = SMAABlendingWeightCalculationPS(frag_tex_coord, pixcoord, offset, color_texture, areaTex, searchTex, subsampleIndices);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
|
|
@ -28,11 +25,9 @@ layout(location = 0) in vec2 frag_tex_coord;
|
|||
layout(location = 1) in vec2 pixcoord;
|
||||
layout(location = 2) in vec4 offset[3];
|
||||
layout(location = 0) out vec4 color;
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
/*
|
||||
screen_textures[0] = color_texture
|
||||
screen_textures[1] = areaTex;
|
||||
screen_textures[2] = searchTex;
|
||||
*/
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture;
|
||||
layout (set = 0, binding = 1) uniform sampler2D areaTex;
|
||||
layout (set = 0, binding = 2) uniform sampler2D searchTex;
|
||||
|
||||
#define SMAA_INCLUDE_VS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -13,9 +13,6 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ vec3 LinearTosRGB(vec3 c) {
|
|||
}
|
||||
|
||||
void main() {
|
||||
vec4 pixel = SMAANeighborhoodBlendingPS(frag_tex_coord, offset, screen_textures[1], screen_textures[0]);
|
||||
vec4 pixel = SMAANeighborhoodBlendingPS(frag_tex_coord, offset, SMAA_Input, color_texture);
|
||||
if (convert_colors == 2){
|
||||
pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
|
|
@ -25,10 +22,8 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 1) in vec4 offset;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
/*
|
||||
screen_textures[0] = color_texture
|
||||
screen_textures[1] = SMAA_Input;
|
||||
*/
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture;
|
||||
layout (set = 0, binding = 1) uniform sampler2D SMAA_Input;
|
||||
|
||||
#define SMAA_INCLUDE_VS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -13,9 +13,6 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// FSR - [EASU] EDGE ADAPTIVE SPATIAL UPSAMPLING
|
||||
// SM 4.0 compatible: no textureGather, direct texelFetch of 12 unique texels.
|
||||
layout(location = 0) in vec2 vert_position;
|
||||
layout(location = 1) in vec2 vert_tex_coord;
|
||||
layout(location = 0) out vec2 frag_tex_coord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// FSR - [EASU] EDGE ADAPTIVE SPATIAL UPSAMPLING
|
||||
// SM 4.0 compatible: no textureGather, direct texelFetch of 12 unique texels.
|
||||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(binding = 0) uniform sampler2D color_texture;
|
||||
uniform vec4 i_resolution;
|
||||
uniform vec4 o_resolution;
|
||||
|
||||
#define A_GPU 1
|
||||
#define A_GLSL 1
|
||||
// #include "ffx_a.h"
|
||||
|
||||
// // We intentionally do NOT define FSR_EASU_F here.
|
||||
// // We only need FsrEasuCon (which compiles under A_GPU alone),
|
||||
// // and we inline the EASU filter logic below to avoid the
|
||||
// // textureGather-based callback system entirely.
|
||||
// // This yields 12 texelFetch calls instead of the original
|
||||
// // 12 textureGather calls (4 gathers x 3 channels), and is
|
||||
// // faster than emulating gathers with 48 individual fetches.
|
||||
// #include "ffx_fsr1.h"
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
void main() {
|
||||
// --- Setup constants (same as original) ---
|
||||
AU4 con0, con1, con2, con3;
|
||||
FsrEasuCon(con0, con1, con2, con3,
|
||||
i_resolution.x, i_resolution.y,
|
||||
i_resolution.x, i_resolution.y,
|
||||
o_resolution.x, o_resolution.y);
|
||||
|
||||
AU2 gxy = AU2(frag_tex_coord.xy * o_resolution.xy);
|
||||
|
||||
// --- Get position of 'f' (the center texel of the kernel) ---
|
||||
AF2 pp = AF2(gxy) * AF2_AU2(con0.xy) + AF2_AU2(con0.zw);
|
||||
AF2 fp = floor(pp);
|
||||
pp -= fp;
|
||||
|
||||
// --- Fetch all 12 unique texels directly as RGB ---
|
||||
// The 12-tap kernel layout relative to 'fp':
|
||||
// b c (0,-1) (1,-1)
|
||||
// e f g h (-1,0) (0,0) (1,0) (2,0)
|
||||
// i j k l (-1,1) (0,1) (1,1) (2,1)
|
||||
// n o (0, 2) (1, 2)
|
||||
ivec2 sp = ivec2(fp);
|
||||
AF3 b = texelFetch(color_texture, sp + ivec2( 0,-1), 0).rgb;
|
||||
AF3 c = texelFetch(color_texture, sp + ivec2( 1,-1), 0).rgb;
|
||||
AF3 e = texelFetch(color_texture, sp + ivec2(-1, 0), 0).rgb;
|
||||
AF3 f = texelFetch(color_texture, sp + ivec2( 0, 0), 0).rgb;
|
||||
AF3 g = texelFetch(color_texture, sp + ivec2( 1, 0), 0).rgb;
|
||||
AF3 h = texelFetch(color_texture, sp + ivec2( 2, 0), 0).rgb;
|
||||
AF3 i = texelFetch(color_texture, sp + ivec2(-1, 1), 0).rgb;
|
||||
AF3 j = texelFetch(color_texture, sp + ivec2( 0, 1), 0).rgb;
|
||||
AF3 k = texelFetch(color_texture, sp + ivec2( 1, 1), 0).rgb;
|
||||
AF3 l = texelFetch(color_texture, sp + ivec2( 2, 1), 0).rgb;
|
||||
AF3 n = texelFetch(color_texture, sp + ivec2( 0, 2), 0).rgb;
|
||||
AF3 o = texelFetch(color_texture, sp + ivec2( 1, 2), 0).rgb;
|
||||
|
||||
// --- Approximate luma (luma times 2, in 2 FMA/MAD) ---
|
||||
AF1 bL = b.b * AF1_(0.5) + (b.r * AF1_(0.5) + b.g);
|
||||
AF1 cL = c.b * AF1_(0.5) + (c.r * AF1_(0.5) + c.g);
|
||||
AF1 eL = e.b * AF1_(0.5) + (e.r * AF1_(0.5) + e.g);
|
||||
AF1 fL = f.b * AF1_(0.5) + (f.r * AF1_(0.5) + f.g);
|
||||
AF1 gL = g.b * AF1_(0.5) + (g.r * AF1_(0.5) + g.g);
|
||||
AF1 hL = h.b * AF1_(0.5) + (h.r * AF1_(0.5) + h.g);
|
||||
AF1 iL = i.b * AF1_(0.5) + (i.r * AF1_(0.5) + i.g);
|
||||
AF1 jL = j.b * AF1_(0.5) + (j.r * AF1_(0.5) + j.g);
|
||||
AF1 kL = k.b * AF1_(0.5) + (k.r * AF1_(0.5) + k.g);
|
||||
AF1 lL = l.b * AF1_(0.5) + (l.r * AF1_(0.5) + l.g);
|
||||
AF1 nL = n.b * AF1_(0.5) + (n.r * AF1_(0.5) + n.g);
|
||||
AF1 oL = o.b * AF1_(0.5) + (o.r * AF1_(0.5) + o.g);
|
||||
|
||||
// --- Accumulate direction and length ---
|
||||
// Inlined FsrEasuSetF for each of the 4 bilinear quadrants.
|
||||
// Each quadrant computes gradient direction and edge length
|
||||
// from its 5-tap cross pattern centered on the quadrant's
|
||||
// nearest texel.
|
||||
//
|
||||
// Quadrant layout (bilinear weights):
|
||||
// s=(1-x)(1-y) t=x(1-y)
|
||||
// u=(1-x)y v=xy
|
||||
//
|
||||
// Cross pattern for each quadrant:
|
||||
// s: center=f, left=e, right=g, up=b, down=j
|
||||
// t: center=g, left=f, right=h, up=c, down=k
|
||||
// u: center=j, left=i, right=k, up=f, down=n
|
||||
// v: center=k, left=j, right=l, up=g, down=o
|
||||
|
||||
AF2 dir = AF2_(0.0);
|
||||
AF1 len = AF1_(0.0);
|
||||
|
||||
// Quadrant s
|
||||
{
|
||||
AF1 w = (AF1_(1.0) - pp.x) * (AF1_(1.0) - pp.y);
|
||||
AF1 dc = gL - fL; AF1 cb = fL - eL;
|
||||
AF1 lenX = max(abs(dc), abs(cb));
|
||||
lenX = APrxLoRcpF1(lenX);
|
||||
AF1 dirX = gL - eL;
|
||||
dir.x += dirX * w;
|
||||
lenX = ASatF1(abs(dirX) * lenX); lenX *= lenX; len += lenX * w;
|
||||
AF1 ec = jL - fL; AF1 ca = fL - bL;
|
||||
AF1 lenY = max(abs(ec), abs(ca));
|
||||
lenY = APrxLoRcpF1(lenY);
|
||||
AF1 dirY = jL - bL;
|
||||
dir.y += dirY * w;
|
||||
lenY = ASatF1(abs(dirY) * lenY); lenY *= lenY; len += lenY * w;
|
||||
}
|
||||
// Quadrant t
|
||||
{
|
||||
AF1 w = pp.x * (AF1_(1.0) - pp.y);
|
||||
AF1 dc = hL - gL; AF1 cb = gL - fL;
|
||||
AF1 lenX = max(abs(dc), abs(cb));
|
||||
lenX = APrxLoRcpF1(lenX);
|
||||
AF1 dirX = hL - fL;
|
||||
dir.x += dirX * w;
|
||||
lenX = ASatF1(abs(dirX) * lenX); lenX *= lenX; len += lenX * w;
|
||||
AF1 ec = kL - gL; AF1 ca = gL - cL;
|
||||
AF1 lenY = max(abs(ec), abs(ca));
|
||||
lenY = APrxLoRcpF1(lenY);
|
||||
AF1 dirY = kL - cL;
|
||||
dir.y += dirY * w;
|
||||
lenY = ASatF1(abs(dirY) * lenY); lenY *= lenY; len += lenY * w;
|
||||
}
|
||||
// Quadrant u
|
||||
{
|
||||
AF1 w = (AF1_(1.0) - pp.x) * pp.y;
|
||||
AF1 dc = kL - jL; AF1 cb = jL - iL;
|
||||
AF1 lenX = max(abs(dc), abs(cb));
|
||||
lenX = APrxLoRcpF1(lenX);
|
||||
AF1 dirX = kL - iL;
|
||||
dir.x += dirX * w;
|
||||
lenX = ASatF1(abs(dirX) * lenX); lenX *= lenX; len += lenX * w;
|
||||
AF1 ec = nL - jL; AF1 ca = jL - fL;
|
||||
AF1 lenY = max(abs(ec), abs(ca));
|
||||
lenY = APrxLoRcpF1(lenY);
|
||||
AF1 dirY = nL - fL;
|
||||
dir.y += dirY * w;
|
||||
lenY = ASatF1(abs(dirY) * lenY); lenY *= lenY; len += lenY * w;
|
||||
}
|
||||
// Quadrant v
|
||||
{
|
||||
AF1 w = pp.x * pp.y;
|
||||
AF1 dc = lL - kL; AF1 cb = kL - jL;
|
||||
AF1 lenX = max(abs(dc), abs(cb));
|
||||
lenX = APrxLoRcpF1(lenX);
|
||||
AF1 dirX = lL - jL;
|
||||
dir.x += dirX * w;
|
||||
lenX = ASatF1(abs(dirX) * lenX); lenX *= lenX; len += lenX * w;
|
||||
AF1 ec = oL - kL; AF1 ca = kL - gL;
|
||||
AF1 lenY = max(abs(ec), abs(ca));
|
||||
lenY = APrxLoRcpF1(lenY);
|
||||
AF1 dirY = oL - gL;
|
||||
dir.y += dirY * w;
|
||||
lenY = ASatF1(abs(dirY) * lenY); lenY *= lenY; len += lenY * w;
|
||||
}
|
||||
|
||||
// --- Normalize direction ---
|
||||
AF2 dir2 = dir * dir;
|
||||
AF1 dirR = dir2.x + dir2.y;
|
||||
AP1 zro = dirR < AF1_(1.0 / 32768.0);
|
||||
dirR = APrxLoRsqF1(dirR);
|
||||
dirR = zro ? AF1_(1.0) : dirR;
|
||||
dir.x = zro ? AF1_(1.0) : dir.x;
|
||||
dir *= AF2_(dirR);
|
||||
|
||||
// --- Shape length ---
|
||||
len = len * AF1_(0.5);
|
||||
len *= len;
|
||||
AF1 stretch = (dir.x * dir.x + dir.y * dir.y) * APrxLoRcpF1(max(abs(dir.x), abs(dir.y)));
|
||||
AF2 len2 = AF2(AF1_(1.0) + (stretch - AF1_(1.0)) * len, AF1_(1.0) + AF1_(-0.5) * len);
|
||||
AF1 lob = AF1_(0.5) + AF1_((1.0 / 4.0 - 0.04) - 0.5) * len;
|
||||
AF1 clp = APrxLoRcpF1(lob);
|
||||
|
||||
// --- Min/max of 4 nearest (f, g, j, k) for de-ringing ---
|
||||
AF3 min4 = min(min(f, g), min(j, k));
|
||||
AF3 max4 = max(max(f, g), max(j, k));
|
||||
|
||||
// --- Accumulate 12 taps (inlined FsrEasuTapF) ---
|
||||
AF3 aC = AF3_(0.0);
|
||||
AF1 aW = AF1_(0.0);
|
||||
|
||||
// Macro for the Lanczos-like kernel evaluation per tap.
|
||||
// Rotates offset by direction, applies anisotropic scaling,
|
||||
// evaluates the approximated windowed Lanczos kernel, accumulates.
|
||||
#define FSR_EASU_TAP(OFF_X, OFF_Y, COLOR) { \
|
||||
AF2 v; \
|
||||
v.x = ((OFF_X) - pp.x) * dir.x + ((OFF_Y) - pp.y) * dir.y; \
|
||||
v.y = ((OFF_X) - pp.x) * (-dir.y) + ((OFF_Y) - pp.y) * dir.x; \
|
||||
v *= len2; \
|
||||
AF1 d2 = min(v.x * v.x + v.y * v.y, clp); \
|
||||
AF1 wB = AF1_(2.0 / 5.0) * d2 + AF1_(-1.0); \
|
||||
AF1 wA = lob * d2 + AF1_(-1.0); \
|
||||
wB *= wB; wA *= wA; \
|
||||
wB = AF1_(25.0 / 16.0) * wB + AF1_(-(25.0 / 16.0 - 1.0)); \
|
||||
AF1 w = wB * wA; \
|
||||
aC += (COLOR) * w; aW += w; }
|
||||
|
||||
FSR_EASU_TAP( 0.0, -1.0, b) // b
|
||||
FSR_EASU_TAP( 1.0, -1.0, c) // c
|
||||
FSR_EASU_TAP(-1.0, 1.0, i) // i
|
||||
FSR_EASU_TAP( 0.0, 1.0, j) // j
|
||||
FSR_EASU_TAP( 0.0, 0.0, f) // f
|
||||
FSR_EASU_TAP(-1.0, 0.0, e) // e
|
||||
FSR_EASU_TAP( 1.0, 1.0, k) // k
|
||||
FSR_EASU_TAP( 2.0, 1.0, l) // l
|
||||
FSR_EASU_TAP( 2.0, 0.0, h) // h
|
||||
FSR_EASU_TAP( 1.0, 0.0, g) // g
|
||||
FSR_EASU_TAP( 1.0, 2.0, o) // o
|
||||
FSR_EASU_TAP( 0.0, 2.0, n) // n
|
||||
|
||||
#undef FSR_EASU_TAP
|
||||
|
||||
// --- Normalize and de-ring ---
|
||||
AF3 pix = min(max4, max(min4, aC * AF3_(ARcpF1(aW))));
|
||||
color = vec4(pix, 1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// FSR - [RCAS] ROBUST CONTRAST ADAPTIVE SHARPENING
|
||||
//? #version 450
|
||||
layout(location = 0) in vec2 vert_position;
|
||||
layout(location = 1) in vec2 vert_tex_coord;
|
||||
layout(location = 0) out vec2 frag_tex_coord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// FSR - [RCAS] ROBUST CONTRAST ADAPTIVE SHARPENING
|
||||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(binding = 0) uniform sampler2D color_texture;
|
||||
uniform float FSR_SHARPENING;
|
||||
uniform vec4 o_resolution;
|
||||
|
||||
#define A_GPU 1
|
||||
#define A_GLSL 1
|
||||
// #include "ffx_a.h"
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#define FSR_RCAS_F 1
|
||||
AU4 con0;
|
||||
|
||||
AF4 FsrRcasLoadF(ASU2 p) { return AF4(texelFetch(color_texture, p, 0)); }
|
||||
void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {}
|
||||
|
||||
// #include "ffx_fsr1.h"
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
void main() {
|
||||
FsrRcasCon(con0, FSR_SHARPENING);
|
||||
|
||||
AU2 gxy = AU2(frag_tex_coord.xy * o_resolution.xy); // Integer pixel position in output.
|
||||
AF3 Gamma2Color = AF3(0, 0, 0);
|
||||
FsrRcasF(Gamma2Color.r, Gamma2Color.g, Gamma2Color.b, gxy, con0);
|
||||
|
||||
color = vec4(Gamma2Color, 1.0);
|
||||
}
|
||||
2656
src/video_core/host_shaders/scaling/FSR/ffx_a.h
Normal file
2656
src/video_core/host_shaders/scaling/FSR/ffx_a.h
Normal file
File diff suppressed because it is too large
Load diff
1199
src/video_core/host_shaders/scaling/FSR/ffx_fsr1.h
Normal file
1199
src/video_core/host_shaders/scaling/FSR/ffx_fsr1.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Author: KojoZero (modified from rsn8887's shader)
|
||||
License: Public domain
|
||||
|
||||
This is an integer prescale filter that should be combined
|
||||
with a bilinear hardware filtering (GL_BILINEAR filter or some such) to achieve
|
||||
a smooth scaling result with minimum blur. This is good for pixelgraphics
|
||||
that are scaled by non-integer factors.
|
||||
|
||||
This is a modified version rsn8887's shader which has been modified to scale
|
||||
until above the output resolution, rather than right below the output resolution.
|
||||
|
||||
The prescale factor and texel coordinates are precalculated
|
||||
in the vertex shader for speed.
|
||||
*/
|
||||
|
||||
|
||||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 1) in vec2 precalc_texel;
|
||||
layout(location = 2) in vec2 precalc_scale;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(binding = 0) uniform sampler2D color_texture;
|
||||
uniform vec4 i_resolution;
|
||||
uniform vec4 o_resolution;
|
||||
uniform int convert_colors;
|
||||
|
||||
vec3 LinearTosRGB(vec3 c) {
|
||||
return mix(c * 12.92, 1.055 * pow(c, vec3(1.0/2.4)) - 0.055, step(0.0031308, c));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texel = precalc_texel;
|
||||
vec2 scale = precalc_scale;
|
||||
vec2 texel_floored = floor(texel);
|
||||
vec2 s = fract(texel);
|
||||
vec2 region_range = 0.5 - 0.5 / scale;
|
||||
|
||||
// Figure out where in the texel to sample to get correct pre-scaled bilinear.
|
||||
// Uses the hardware bilinear interpolator to avoid having to sample 4 times manually.
|
||||
|
||||
vec2 center_dist = s - 0.5;
|
||||
vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5;
|
||||
|
||||
vec2 mod_texel = texel_floored + f;
|
||||
|
||||
vec4 pixel = vec4(texture(color_texture, mod_texel / i_resolution.xy).rgb, 1.0);
|
||||
if (convert_colors == 2){
|
||||
pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a);
|
||||
}
|
||||
color = pixel;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
layout(location = 0) in vec2 vert_position;
|
||||
layout(location = 1) in vec2 vert_tex_coord;
|
||||
layout(location = 0) out vec2 frag_tex_coord;
|
||||
layout(location = 1) out vec2 precalc_texel;
|
||||
layout(location = 2) out vec2 precalc_scale;
|
||||
uniform mat3x2 modelview_matrix;
|
||||
uniform vec4 i_resolution;
|
||||
uniform vec4 o_resolution;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
precalc_scale = ceil(o_resolution.xy / i_resolution.xy);
|
||||
precalc_texel = vert_tex_coord.xy * i_resolution.xy;
|
||||
}
|
||||
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
/*
|
||||
screen_textures[0] = color_texture
|
||||
*/
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
|
|
@ -15,9 +13,6 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
|
||||
/***** Area Sampling *****/
|
||||
|
|
@ -97,7 +92,7 @@ vec3 LinearTosRGB(vec3 c) {
|
|||
}
|
||||
|
||||
void main() {
|
||||
vec4 pixel = AreaSampling(screen_textures[0], frag_tex_coord);
|
||||
vec4 pixel = AreaSampling(color_texture, frag_tex_coord);
|
||||
if (convert_colors == 2){
|
||||
pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
void main()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,25 +16,25 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
vec4 GetScreen(int screen_id) {
|
||||
#ifdef ARRAY_DYNAMIC_INDEX
|
||||
return texture(screen_textures[screen_id], frag_tex_coord);
|
||||
#else
|
||||
switch (screen_id) {
|
||||
case 0:
|
||||
return texture(screen_textures[0], frag_tex_coord);
|
||||
case 1:
|
||||
return texture(screen_textures[1], frag_tex_coord);
|
||||
case 2:
|
||||
return texture(screen_textures[2], frag_tex_coord);
|
||||
}
|
||||
#endif
|
||||
vec3 sRGBToLinear(vec3 c) {
|
||||
return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(0.04045, c));
|
||||
}
|
||||
|
||||
vec3 LinearTosRGB(vec3 c) {
|
||||
return mix(c * 12.92, 1.055 * pow(c, vec3(1.0/2.4)) - 0.055, step(0.0031308, c));
|
||||
}
|
||||
|
||||
void main() {
|
||||
color = GetScreen(screen_id_l);
|
||||
vec4 pixel = texture(color_texture, frag_tex_coord);
|
||||
if (convert_colors == 2){
|
||||
pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a);
|
||||
} else if (convert_colors == 1){
|
||||
pixel = vec4(sRGBToLinear(pixel.rgb), pixel.a);
|
||||
}
|
||||
color = pixel;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,25 +30,11 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int reverse_interlaced;
|
||||
};
|
||||
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
|
||||
vec4 GetScreen(int screen_id) {
|
||||
#ifdef ARRAY_DYNAMIC_INDEX
|
||||
return texture(screen_textures[screen_id], frag_tex_coord);
|
||||
#else
|
||||
switch (screen_id) {
|
||||
case 0:
|
||||
return texture(screen_textures[0], frag_tex_coord);
|
||||
case 1:
|
||||
return texture(screen_textures[1], frag_tex_coord);
|
||||
case 2:
|
||||
return texture(screen_textures[2], frag_tex_coord);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture_l;
|
||||
layout (set = 0, binding = 1) uniform sampler2D color_texture_r;
|
||||
|
||||
void main() {
|
||||
vec4 color_tex_l = GetScreen(screen_id_l);
|
||||
vec4 color_tex_r = GetScreen(screen_id_r);
|
||||
vec4 color_tex_l = texture(color_texture_l, frag_tex_coord);
|
||||
vec4 color_tex_r = texture(color_texture_r, frag_tex_coord);
|
||||
color = vec4(color_tex_l.rgb*l+color_tex_r.rgb*r, color_tex_l.a);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,27 +18,13 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int reverse_interlaced;
|
||||
};
|
||||
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
|
||||
vec4 GetScreen(int screen_id) {
|
||||
#ifdef ARRAY_DYNAMIC_INDEX
|
||||
return texture(screen_textures[screen_id], frag_tex_coord);
|
||||
#else
|
||||
switch (screen_id) {
|
||||
case 0:
|
||||
return texture(screen_textures[0], frag_tex_coord);
|
||||
case 1:
|
||||
return texture(screen_textures[1], frag_tex_coord);
|
||||
case 2:
|
||||
return texture(screen_textures[2], frag_tex_coord);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture_l;
|
||||
layout (set = 0, binding = 1) uniform sampler2D color_texture_r;
|
||||
|
||||
void main() {
|
||||
float screen_row = o_resolution.x * frag_tex_coord.x;
|
||||
if (int(screen_row) % 2 == reverse_interlaced)
|
||||
color = GetScreen(screen_id_l);
|
||||
color = texture(color_texture_l, frag_tex_coord);
|
||||
else
|
||||
color = GetScreen(screen_id_r);
|
||||
color = texture(color_texture_r, frag_tex_coord);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,22 +19,7 @@ layout (push_constant, std140) uniform DrawInfo {
|
|||
int convert_colors;
|
||||
};
|
||||
|
||||
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
|
||||
|
||||
vec4 GetScreen(int screen_id) {
|
||||
#ifdef ARRAY_DYNAMIC_INDEX
|
||||
return texture(screen_textures[screen_id], frag_tex_coord);
|
||||
#else
|
||||
switch (screen_id) {
|
||||
case 0:
|
||||
return texture(screen_textures[0], frag_tex_coord);
|
||||
case 1:
|
||||
return texture(screen_textures[1], frag_tex_coord);
|
||||
case 2:
|
||||
return texture(screen_textures[2], frag_tex_coord);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
vec3 sRGBToLinear(vec3 c) {
|
||||
return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(0.04045, c));
|
||||
|
|
@ -45,7 +30,7 @@ vec3 LinearTosRGB(vec3 c) {
|
|||
}
|
||||
|
||||
void main() {
|
||||
vec4 pixel = GetScreen(screen_id_l);
|
||||
vec4 pixel = texture(color_texture, frag_tex_coord);
|
||||
if (convert_colors == 2){
|
||||
pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a);
|
||||
} else if (convert_colors == 1){
|
||||
|
|
|
|||
|
|
@ -44,6 +44,17 @@
|
|||
#include "video_core/host_shaders/antialiasing/SearchTex.h"
|
||||
#include "video_core/host_shaders/scaling/opengl_area_sampling_frag.h"
|
||||
#include "video_core/host_shaders/scaling/opengl_area_sampling_vert.h"
|
||||
#include "video_core/host_shaders/scaling/FSR/OpenGL/opengl_fsr_pass0_vert.h"
|
||||
#include "video_core/host_shaders/scaling/FSR/OpenGL/opengl_fsr_pass0_part1_frag.h"
|
||||
#include "video_core/host_shaders/scaling/FSR/OpenGL/opengl_fsr_pass0_part2_frag.h"
|
||||
#include "video_core/host_shaders/scaling/FSR/OpenGL/opengl_fsr_pass1_vert.h"
|
||||
#include "video_core/host_shaders/scaling/FSR/OpenGL/opengl_fsr_pass1_part1_frag.h"
|
||||
#include "video_core/host_shaders/scaling/FSR/OpenGL/opengl_fsr_pass1_part2_frag.h"
|
||||
#include "video_core/host_shaders/scaling/FSR/OpenGL/opengl_fsr_pass1_part3_frag.h"
|
||||
#include "video_core/host_shaders/scaling/FSR/ffx_a_h.h"
|
||||
#include "video_core/host_shaders/scaling/FSR/ffx_fsr1_h.h"
|
||||
#include "video_core/host_shaders/scaling/SharpBilinear/OpenGL/opengl_sharpbilinear_vert.h"
|
||||
#include "video_core/host_shaders/scaling/SharpBilinear/OpenGL/opengl_sharpbilinear_frag.h"
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
|
|
@ -381,22 +392,37 @@ void RendererOpenGL::AllocateSMAATextures(){
|
|||
}
|
||||
|
||||
void RendererOpenGL::AllocatePPTextures(){
|
||||
for (int i = 0; i < 5; i++){
|
||||
intermediateTextureTop[i].Release();
|
||||
intermediateTextureTop[i].Create();
|
||||
intermediateTextureTop[i].Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currTopTextureWidth, currTopTextureHeight);
|
||||
intermediateTextureBottom[i].Release();
|
||||
intermediateTextureBottom[i].Create();
|
||||
intermediateTextureBottom[i].Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currBottomTextureWidth, currBottomTextureHeight);
|
||||
}
|
||||
antialiasFBOTextureTop.Release();
|
||||
antialiasFBOTextureTop.Create();
|
||||
antialiasFBOTextureTop.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currTopTextureWidth, currTopTextureHeight);
|
||||
antialiasFBOTextureBottom.Release();
|
||||
antialiasFBOTextureBottom.Create();
|
||||
antialiasFBOTextureBottom.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currBottomTextureWidth, currBottomTextureHeight);
|
||||
|
||||
LOG_INFO(Render_OpenGL, "Reallocated Shaders");
|
||||
|
||||
for (int j = 0; j < intermediateTextures[0].size(); j++){
|
||||
intermediateTextures[0][j].Release();
|
||||
intermediateTextures[0][j].Create();
|
||||
intermediateTextures[0][j].Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currTopTextureWidth, currTopTextureHeight);
|
||||
intermediateTextures[1][j].Release();
|
||||
intermediateTextures[1][j].Create();
|
||||
intermediateTextures[1][j].Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currBottomTextureWidth, currBottomTextureHeight);
|
||||
}
|
||||
antialiasFBOTexture[0].Release();
|
||||
antialiasFBOTexture[0].Create();
|
||||
antialiasFBOTexture[0].Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currTopTextureWidth, currTopTextureHeight);
|
||||
antialiasFBOTexture[1].Release();
|
||||
antialiasFBOTexture[1].Create();
|
||||
antialiasFBOTexture[1].Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currBottomTextureWidth, currBottomTextureHeight);
|
||||
LOG_INFO(Render_OpenGL, "Reallocated Textures");
|
||||
}
|
||||
|
||||
void RendererOpenGL::AllocateOutputSizeTextures(){
|
||||
for (int i = 0; i < intermediateOutputSizeTextures.size(); i++){
|
||||
if (currOutputScreenRects[i].GetHeight() != 0 && currOutputScreenRects[i].GetWidth() != 0){
|
||||
for (int j = 0; j < intermediateOutputSizeTextures[0].size(); j++){
|
||||
intermediateOutputSizeTextures[i][j].Release();
|
||||
intermediateOutputSizeTextures[i][j].Create();
|
||||
intermediateOutputSizeTextures[i][j].Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currOutputScreenRects[i].GetWidth(), currOutputScreenRects[i].GetHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO(Render_OpenGL, "Reallocated OutputSize Textures");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -548,7 +574,23 @@ void RendererOpenGL::ReloadShader(Settings::StereoRenderOption render_3d) {
|
|||
SMAA_PASS_2_shader.Create(SMAA_PASS_2_shader_vert_data, SMAA_PASS_2_shader_frag_data);
|
||||
|
||||
|
||||
//
|
||||
std::string FSR_PASS_0_shader_frag_data = fragment_shader_precision_OES;
|
||||
FSR_PASS_0_shader_frag_data += HostShaders::OPENGL_FSR_PASS0_PART1_FRAG;
|
||||
FSR_PASS_0_shader_frag_data += HostShaders::FFX_A_H;
|
||||
FSR_PASS_0_shader_frag_data += HostShaders::FFX_FSR1_H;
|
||||
FSR_PASS_0_shader_frag_data += HostShaders::OPENGL_FSR_PASS0_PART2_FRAG;
|
||||
FSR_PASS_0_shader.Create(HostShaders::OPENGL_FSR_PASS0_VERT, FSR_PASS_0_shader_frag_data);
|
||||
|
||||
std::string FSR_PASS_1_shader_frag_data = fragment_shader_precision_OES;
|
||||
FSR_PASS_1_shader_frag_data += HostShaders::OPENGL_FSR_PASS1_PART1_FRAG;
|
||||
FSR_PASS_1_shader_frag_data += HostShaders::FFX_A_H;
|
||||
FSR_PASS_1_shader_frag_data += HostShaders::OPENGL_FSR_PASS1_PART2_FRAG;
|
||||
FSR_PASS_1_shader_frag_data += HostShaders::FFX_FSR1_H;
|
||||
FSR_PASS_1_shader_frag_data += HostShaders::OPENGL_FSR_PASS1_PART3_FRAG;
|
||||
FSR_PASS_1_shader.Create(HostShaders::OPENGL_FSR_PASS1_VERT, FSR_PASS_1_shader_frag_data);
|
||||
|
||||
SharpBilinear_shader.Create(HostShaders::OPENGL_SHARPBILINEAR_VERT, HostShaders::OPENGL_SHARPBILINEAR_FRAG);
|
||||
|
||||
state.Apply();
|
||||
if (render_3d == Settings::StereoRenderOption::Anaglyph ||
|
||||
render_3d == Settings::StereoRenderOption::Interlaced ||
|
||||
|
|
@ -639,6 +681,7 @@ void RendererOpenGL::AttachUniforms(){
|
|||
uniform_i_resolution = glGetUniformLocation(state.draw.shader_program, "i_resolution");
|
||||
uniform_o_resolution = glGetUniformLocation(state.draw.shader_program, "o_resolution");
|
||||
uniform_convert_colors = glGetUniformLocation(state.draw.shader_program, "convert_colors");
|
||||
uniform_fsr_sharpening = glGetUniformLocation(state.draw.shader_program, "FSR_SHARPENING");
|
||||
uniform_layer = glGetUniformLocation(state.draw.shader_program, "layer");
|
||||
attrib_position = glGetAttribLocation(state.draw.shader_program, "vert_position");
|
||||
attrib_tex_coord = glGetAttribLocation(state.draw.shader_program, "vert_tex_coord");
|
||||
|
|
@ -654,23 +697,19 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
const u32 scale_factor = GetResolutionScaleFactor();
|
||||
float textureWidth = static_cast<float>(screen_info.texture.height * scale_factor);
|
||||
float textureHeight = static_cast<float>(screen_info.texture.width * scale_factor);
|
||||
int currScreen;
|
||||
if (textureWidth == currTopTextureWidth && textureHeight == currTopTextureHeight){
|
||||
currAntialiasFBOTexture = &antialiasFBOTextureTop;
|
||||
currIntermediateTexture = &intermediateTextureTop;
|
||||
currScreen = 0;
|
||||
} else {
|
||||
currAntialiasFBOTexture = &antialiasFBOTextureBottom;
|
||||
currIntermediateTexture = &intermediateTextureBottom;
|
||||
currScreen = 1;
|
||||
}
|
||||
|
||||
// Texture Width and Height when correctly rotated to landscape
|
||||
bool isDownsampling = false;
|
||||
int scalingMode; //0 is Nearest Neighbor, 1 is Gamma Corrected Bilinear, 2 is High Quality Scaling (Upsampling via Gamma Corrected Bilinear, Downsampling is Gamma Corrected Area Sampling)
|
||||
if (Settings::values.filter_mode.GetValue()){
|
||||
scalingMode = 2;
|
||||
} else {
|
||||
scalingMode = 0;
|
||||
}
|
||||
int scalingMode; //0 is Nearest Neighbor, 1 is Gamma Corrected Bilinear, 2 is Adaptive (Bilinear/Area), 3 is FSR, 4 is Sharp Bilinear
|
||||
scalingMode = static_cast<int>(Settings::values.output_scaling.GetValue());
|
||||
int antialiasingMode = static_cast<int>(Settings::values.antialiasing_filter.GetValue()); //0 is none, 1 is FXAA, 2 is SMAA
|
||||
float fsr_sharpening = 2 - (2 * (Settings::values.fsr_sharpness.GetValue()/ 100.0f));
|
||||
if (orientation == Layout::DisplayOrientation::Landscape || orientation == Layout::DisplayOrientation::LandscapeFlipped) {
|
||||
if (textureWidth > screenWidth){
|
||||
isDownsampling = true;
|
||||
|
|
@ -752,7 +791,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.viewport.width = textureWidth;
|
||||
state.viewport.height = textureHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, (*currIntermediateTexture)[0].handle, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateTextures[currScreen][0].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SimplePresent_shader.handle;
|
||||
state.Apply();
|
||||
|
|
@ -771,15 +810,19 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.viewport.width = textureWidth;
|
||||
state.viewport.height = textureHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, (*currAntialiasFBOTexture).handle, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, antialiasFBOTexture[currScreen].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = FXAA_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = (*currIntermediateTexture)[0].handle;
|
||||
state.texture_units[0].texture_2d = intermediateTextures[currScreen][0].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_convert_colors, 1);
|
||||
if (scalingMode == 3){
|
||||
glUniform1i(uniform_convert_colors, 0);
|
||||
} else {
|
||||
glUniform1i(uniform_convert_colors, 1);
|
||||
}
|
||||
glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight);
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data());
|
||||
|
|
@ -795,7 +838,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.viewport.width = textureWidth;
|
||||
state.viewport.height = textureHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, (*currIntermediateTexture)[0].handle, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateTextures[currScreen][0].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SimplePresent_shader.handle;
|
||||
state.Apply();
|
||||
|
|
@ -814,12 +857,12 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.viewport.width = textureWidth;
|
||||
state.viewport.height = textureHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, (*currIntermediateTexture)[3].handle, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateTextures[currScreen][3].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SimplePresent_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = (*currIntermediateTexture)[0].handle;
|
||||
state.texture_units[0].texture_2d = intermediateTextures[currScreen][0].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_convert_colors, 1);
|
||||
|
|
@ -833,12 +876,12 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.viewport.width = textureWidth;
|
||||
state.viewport.height = textureHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, (*currIntermediateTexture)[1].handle, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateTextures[currScreen][1].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SMAA_PASS_0_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = (*currIntermediateTexture)[0].handle;
|
||||
state.texture_units[0].texture_2d = intermediateTextures[currScreen][0].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight);
|
||||
|
|
@ -852,12 +895,12 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.viewport.width = textureWidth;
|
||||
state.viewport.height = textureHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, (*currIntermediateTexture)[2].handle, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateTextures[currScreen][2].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SMAA_PASS_1_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = (*currIntermediateTexture)[1].handle;
|
||||
state.texture_units[0].texture_2d = intermediateTextures[currScreen][1].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
state.texture_units[1].texture_2d = areatex.handle;
|
||||
state.texture_units[1].sampler = samplers[1].handle;
|
||||
|
|
@ -879,19 +922,23 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.viewport.width = textureWidth;
|
||||
state.viewport.height = textureHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, (*currAntialiasFBOTexture).handle, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, antialiasFBOTexture[currScreen].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SMAA_PASS_2_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = (*currIntermediateTexture)[2].handle;
|
||||
state.texture_units[0].texture_2d = intermediateTextures[currScreen][2].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
state.texture_units[1].texture_2d = (*currIntermediateTexture)[3].handle;
|
||||
state.texture_units[1].texture_2d = intermediateTextures[currScreen][3].handle;
|
||||
state.texture_units[1].sampler = samplers[1].handle;
|
||||
GLuint uniform_smaa_input = glGetUniformLocation(state.draw.shader_program, "SMAA_Input");
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_smaa_input, 1);
|
||||
glUniform1i(uniform_convert_colors, 0);
|
||||
if (scalingMode == 3){
|
||||
glUniform1i(uniform_convert_colors, 2);
|
||||
} else {
|
||||
glUniform1i(uniform_convert_colors, 0);
|
||||
}
|
||||
glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight);
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data());
|
||||
|
|
@ -905,7 +952,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.viewport.width = textureWidth;
|
||||
state.viewport.height = textureHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, (*currAntialiasFBOTexture).handle, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, antialiasFBOTexture[currScreen].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SimplePresent_shader.handle;
|
||||
state.Apply();
|
||||
|
|
@ -913,7 +960,11 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.texture_units[0].texture_2d = screen_info.display_texture;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_convert_colors, 1);
|
||||
if (scalingMode == 3){
|
||||
glUniform1i(uniform_convert_colors, 0);
|
||||
} else {
|
||||
glUniform1i(uniform_convert_colors, 1);
|
||||
}
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(rotate_vertices), rotate_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
|
@ -932,7 +983,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.draw.shader_program = AREA_SAMPLING_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = (*currAntialiasFBOTexture).handle;
|
||||
state.texture_units[0].texture_2d = antialiasFBOTexture[currScreen].handle;
|
||||
state.texture_units[0].sampler = samplers[0].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_convert_colors, 2);
|
||||
|
|
@ -955,7 +1006,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.draw.shader_program = Present_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = (*currAntialiasFBOTexture).handle;
|
||||
state.texture_units[0].texture_2d = antialiasFBOTexture[currScreen].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_convert_colors, 2);
|
||||
|
|
@ -964,6 +1015,152 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
} else if (scalingMode == 3){
|
||||
//Use intermiedatetextures[currScreen]
|
||||
if (isDownsampling){
|
||||
// EASU (1x)
|
||||
state.viewport.x = 0;
|
||||
state.viewport.y = 0;
|
||||
state.viewport.width = textureWidth;
|
||||
state.viewport.height = textureHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateTextures[currScreen][4].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = FSR_PASS_0_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = antialiasFBOTexture[currScreen].handle;
|
||||
state.texture_units[0].sampler = samplers[0].handle;
|
||||
glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight);
|
||||
glUniform4f(uniform_o_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight);
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
// RCAS
|
||||
state.viewport.x = 0;
|
||||
state.viewport.y = 0;
|
||||
state.viewport.width = textureWidth;
|
||||
state.viewport.height = textureHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateTextures[currScreen][5].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = FSR_PASS_1_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = intermediateTextures[currScreen][4].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1f(uniform_fsr_sharpening, fsr_sharpening);
|
||||
glUniform4f(uniform_o_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight);
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
// Area Sampling
|
||||
state.draw.read_framebuffer = originalReadFramebuffer;
|
||||
state.draw.draw_framebuffer = originalDrawFramebuffer;
|
||||
state.Apply();
|
||||
state.viewport.x = originalViewport[0];
|
||||
state.viewport.y = originalViewport[1];
|
||||
state.viewport.width = originalViewport[2];
|
||||
state.viewport.height = originalViewport[3];
|
||||
state.Apply();
|
||||
state.draw.shader_program = AREA_SAMPLING_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = intermediateTextures[currScreen][5].handle;
|
||||
state.texture_units[0].sampler = samplers[0].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_convert_colors, 0);
|
||||
glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight);
|
||||
glUniform4f(uniform_o_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight);
|
||||
glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data());
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
} else {
|
||||
// EASU (to output resolution)
|
||||
state.viewport.x = 0;
|
||||
state.viewport.y = 0;
|
||||
state.viewport.width = screenWidth;
|
||||
state.viewport.height = screenHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateOutputSizeTextures[currOutputScreen][1].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = FSR_PASS_0_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = antialiasFBOTexture[currScreen].handle;
|
||||
state.texture_units[0].sampler = samplers[0].handle;
|
||||
glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight);
|
||||
glUniform4f(uniform_o_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight);
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
// RCAS
|
||||
state.viewport.x = 0;
|
||||
state.viewport.y = 0;
|
||||
state.viewport.width = screenWidth;
|
||||
state.viewport.height = screenHeight;
|
||||
state.Apply();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, intermediateOutputSizeTextures[currOutputScreen][2].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = FSR_PASS_1_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = intermediateOutputSizeTextures[currOutputScreen][1].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1f(uniform_fsr_sharpening, fsr_sharpening);
|
||||
glUniform4f(uniform_o_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight);
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
// Normal Present
|
||||
state.draw.read_framebuffer = originalReadFramebuffer;
|
||||
state.draw.draw_framebuffer = originalDrawFramebuffer;
|
||||
state.Apply();
|
||||
state.viewport.x = originalViewport[0];
|
||||
state.viewport.y = originalViewport[1];
|
||||
state.viewport.width = originalViewport[2];
|
||||
state.viewport.height = originalViewport[3];
|
||||
state.Apply();
|
||||
state.draw.shader_program = Present_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = intermediateOutputSizeTextures[currOutputScreen][2].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_convert_colors, 0);
|
||||
glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data());
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
} else if (scalingMode == 4){
|
||||
//Output
|
||||
state.draw.read_framebuffer = originalReadFramebuffer;
|
||||
state.draw.draw_framebuffer = originalDrawFramebuffer;
|
||||
state.Apply();
|
||||
state.viewport.x = originalViewport[0];
|
||||
state.viewport.y = originalViewport[1];
|
||||
state.viewport.width = originalViewport[2];
|
||||
state.viewport.height = originalViewport[3];
|
||||
state.Apply();
|
||||
state.draw.shader_program = SharpBilinear_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = antialiasFBOTexture[currScreen].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_convert_colors, 2);
|
||||
glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight);
|
||||
glUniform4f(uniform_o_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight);
|
||||
glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data());
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
} else {
|
||||
//Output
|
||||
state.draw.read_framebuffer = originalReadFramebuffer;
|
||||
|
|
@ -977,7 +1174,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree
|
|||
state.draw.shader_program = Present_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = (*currAntialiasFBOTexture).handle;
|
||||
state.texture_units[0].texture_2d = antialiasFBOTexture[currScreen].handle;
|
||||
if (scalingMode == 1){
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
} else {
|
||||
|
|
@ -1047,7 +1244,8 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l,
|
|||
}
|
||||
|
||||
const u32 scale_factor = GetResolutionScaleFactor();
|
||||
const GLuint sampler = samplers[Settings::values.filter_mode.GetValue()].handle;
|
||||
int scalingMode = static_cast<int>(Settings::values.output_scaling.GetValue());
|
||||
const GLuint sampler = samplers[scalingMode > 0 ? 1 : 0].handle;
|
||||
glUniform4f(uniform_i_resolution,
|
||||
static_cast<float>(screen_info_l.texture.width * scale_factor),
|
||||
static_cast<float>(screen_info_l.texture.height * scale_factor),
|
||||
|
|
@ -1098,13 +1296,24 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||
currBottomTextureHeight = static_cast<float>(screen_infos[2].texture.width * GetResolutionScaleFactor());
|
||||
if (currTopTextureWidth != prevTopTextureWidth || currTopTextureHeight != prevTopTextureHeight || currBottomTextureWidth != prevBottomTextureWidth || currBottomTextureHeight != prevBottomTextureHeight){
|
||||
AllocatePPTextures();
|
||||
LOG_INFO(Render_OpenGL, "PrevTopTexture Res: {}x{}, CurrTopTexture Res: {}x{}, PrevBottomTexture Res: {}x{}, CurrBottomTexture Res: {}x{}", prevTopTextureWidth, prevTopTextureHeight, currTopTextureWidth, currTopTextureHeight, prevBottomTextureWidth, prevBottomTextureHeight, currBottomTextureWidth, currBottomTextureHeight);
|
||||
// LOG_INFO(Render_OpenGL, "PrevTopTexture Res: {}x{}, CurrTopTexture Res: {}x{}, PrevBottomTexture Res: {}x{}, CurrBottomTexture Res: {}x{}", prevTopTextureWidth, prevTopTextureHeight, currTopTextureWidth, currTopTextureHeight, prevBottomTextureWidth, prevBottomTextureHeight, currBottomTextureWidth, currBottomTextureHeight);
|
||||
}
|
||||
prevTopTextureWidth = currTopTextureWidth;
|
||||
prevTopTextureHeight = currTopTextureHeight;
|
||||
prevBottomTextureWidth = currBottomTextureWidth;
|
||||
prevBottomTextureHeight = currBottomTextureHeight;
|
||||
|
||||
//Track Layout Changes
|
||||
currOutputScreenRects[0] = layout.top_screen;
|
||||
currOutputScreenRects[1] = layout.bottom_screen;
|
||||
currOutputScreenRects[2] = layout.additional_screen;
|
||||
if (currOutputScreenRects[0] != prevOutputScreenRects[0] || currOutputScreenRects[1] != prevOutputScreenRects[1] || currOutputScreenRects[2] != prevOutputScreenRects[2]){
|
||||
AllocateOutputSizeTextures();
|
||||
}
|
||||
prevOutputScreenRects[0] = currOutputScreenRects[0];
|
||||
prevOutputScreenRects[1] = currOutputScreenRects[1];
|
||||
prevOutputScreenRects[2] = currOutputScreenRects[2];
|
||||
|
||||
//Set the Viewport
|
||||
state.viewport.x = 0;
|
||||
state.viewport.y = 0;
|
||||
|
|
@ -1136,18 +1345,23 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||
|
||||
glUniform1i(uniform_layer, 0);
|
||||
if (!Settings::values.swap_screen.GetValue()) {
|
||||
currOutputScreen = 0;
|
||||
DrawTopScreen(layout, top_screen);
|
||||
glUniform1i(uniform_layer, 0);
|
||||
ApplySecondLayerOpacity(layout.bottom_opacity);
|
||||
currOutputScreen = 1;
|
||||
DrawBottomScreen(layout, bottom_screen);
|
||||
} else {
|
||||
currOutputScreen = 1;
|
||||
DrawBottomScreen(layout, bottom_screen);
|
||||
glUniform1i(uniform_layer, 0);
|
||||
ApplySecondLayerOpacity(layout.top_opacity);
|
||||
currOutputScreen = 0;
|
||||
DrawTopScreen(layout, top_screen);
|
||||
}
|
||||
|
||||
if (layout.additional_screen_enabled) {
|
||||
currOutputScreen = 2;
|
||||
const auto& additional_screen = layout.additional_screen;
|
||||
if (!Settings::values.swap_screen.GetValue()) {
|
||||
DrawTopScreen(layout, additional_screen);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ private:
|
|||
void ReloadShader(Settings::StereoRenderOption render_3d);
|
||||
void AllocateSMAATextures();
|
||||
void AllocatePPTextures();
|
||||
void AllocateOutputSizeTextures();
|
||||
void PrepareRendertarget();
|
||||
void RenderScreenshot();
|
||||
void RenderToMailbox(const Layout::FramebufferLayout& layout,
|
||||
|
|
@ -102,19 +103,23 @@ private:
|
|||
OGLProgram SMAA_PASS_1_shader;
|
||||
OGLProgram SMAA_PASS_2_shader;
|
||||
OGLProgram AREA_SAMPLING_shader;
|
||||
OGLProgram FSR_PASS_0_shader;
|
||||
OGLProgram FSR_PASS_1_shader;
|
||||
OGLProgram SharpBilinear_shader;
|
||||
OGLFramebuffer screenshot_framebuffer;
|
||||
std::array<OGLSampler, 2> samplers;
|
||||
|
||||
// OpenGL objects for post processing
|
||||
OGLFramebuffer textureFBO;
|
||||
std::array<OGLTexture, 5> intermediateTextureTop;
|
||||
std::array<OGLTexture, 5> intermediateTextureBottom;
|
||||
OGLTexture antialiasFBOTextureTop;
|
||||
OGLTexture antialiasFBOTextureBottom;
|
||||
//Textures for Top and Bottom Screen Respectively
|
||||
std::array<std::array<OGLTexture, 7>, 2> intermediateTextures;
|
||||
std::array<OGLTexture, 2> antialiasFBOTexture;
|
||||
|
||||
OGLTexture* currAntialiasFBOTexture;
|
||||
std::array<OGLTexture, 5>* currIntermediateTexture;
|
||||
|
||||
//Intermediate Textures at output size. These are for Top Screen, Bottom Screen and Additional Screen Respectively
|
||||
std::array<std::array<OGLTexture, 3>, 3> intermediateOutputSizeTextures;
|
||||
std::array<Common::Rectangle<u32>, 3> prevOutputScreenRects;
|
||||
std::array<Common::Rectangle<u32>, 3> currOutputScreenRects;
|
||||
int currOutputScreen;
|
||||
OGLTexture areatex;
|
||||
OGLTexture searchtex;
|
||||
|
||||
|
|
@ -129,6 +134,8 @@ private:
|
|||
|
||||
// Shader Uniform for converting colors. 0 is no conversion, 1 is sRGB -> linear, 2 is Linear -> sRGB
|
||||
GLuint uniform_convert_colors;
|
||||
|
||||
GLuint uniform_fsr_sharpening;
|
||||
|
||||
// Shader uniform for Dolphin compatibility
|
||||
GLuint uniform_i_resolution;
|
||||
|
|
|
|||
|
|
@ -60,14 +60,6 @@ MICROPROFILE_DEFINE(Vulkan_RenderFrame, "Vulkan", "Render Frame", MP_RGB(128, 12
|
|||
|
||||
namespace Vulkan {
|
||||
|
||||
struct ScreenRectVertex {
|
||||
ScreenRectVertex() = default;
|
||||
ScreenRectVertex(float x, float y, float u, float v)
|
||||
: position{Common::MakeVec(x, y)}, tex_coord{Common::MakeVec(u, v)} {}
|
||||
|
||||
Common::Vec2f position;
|
||||
Common::Vec2f tex_coord;
|
||||
};
|
||||
|
||||
constexpr u32 VERTEX_BUFFER_SIZE = sizeof(ScreenRectVertex) * 8192;
|
||||
|
||||
|
|
@ -80,8 +72,10 @@ constexpr std::array<f32, 4 * 4> MakeOrthographicMatrix(u32 width, u32 height) {
|
|||
// clang-format on
|
||||
}
|
||||
|
||||
constexpr static std::array<vk::DescriptorSetLayoutBinding, 1> PRESENT_BINDINGS = {{
|
||||
{0, vk::DescriptorType::eCombinedImageSampler, 3, vk::ShaderStageFlagBits::eFragment},
|
||||
constexpr static std::array<vk::DescriptorSetLayoutBinding, 3> PRESENT_BINDINGS = {{
|
||||
{0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment},
|
||||
{1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment},
|
||||
{2, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment},
|
||||
}};
|
||||
|
||||
namespace {
|
||||
|
|
@ -153,6 +147,8 @@ RendererVulkan::RendererVulkan(Core::System& system, Pica::PicaCore& pica_,
|
|||
CompileShaders();
|
||||
BuildLayouts();
|
||||
CreateTextureRenderPass();
|
||||
AllocatePPTextures();
|
||||
CreatePPTextureFramebuffers();
|
||||
BuildPipelines();
|
||||
if (secondary_window) {
|
||||
secondary_present_window_ptr = std::make_unique<PresentWindow>(
|
||||
|
|
@ -199,6 +195,18 @@ RendererVulkan::~RendererVulkan() {
|
|||
vmaDestroyImage(instance.GetAllocator(), info.texture.image, info.texture.allocation);
|
||||
}
|
||||
|
||||
for (int j = 0; j < intermediateTextures.size(); j++) {
|
||||
for (int i = 0; i < intermediateTextures[0].size(); i++){
|
||||
device.destroyFramebuffer(intermediateTextureFBOs[j][i]);
|
||||
device.destroyImageView(intermediateTextures[j][i].image_view);
|
||||
vmaDestroyImage(instance.GetAllocator(), intermediateTextures[j][i].image, intermediateTextures[j][i].allocation);
|
||||
|
||||
}
|
||||
device.destroyFramebuffer(antialiasTextureFBOs[j]);
|
||||
device.destroyImageView(antialiasTextures[j].image_view);
|
||||
vmaDestroyImage(instance.GetAllocator(), antialiasTextures[j].image, antialiasTextures[j].allocation);
|
||||
}
|
||||
device.destroyRenderPass(textureRenderpass);
|
||||
device.destroyPipeline(cursor_pipeline);
|
||||
device.destroyShaderModule(cursor_vertex_shader);
|
||||
device.destroyShaderModule(cursor_fragment_shader);
|
||||
|
|
@ -231,7 +239,7 @@ void RendererVulkan::PrepareRendertarget() {
|
|||
void RendererVulkan::CreateTextureRenderPass(){
|
||||
const vk::AttachmentReference color_ref = {
|
||||
.attachment = 0,
|
||||
.layout = vk::ImageLayout::eGeneral,
|
||||
.layout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||
};
|
||||
|
||||
const vk::SubpassDescription subpass = {
|
||||
|
|
@ -246,12 +254,22 @@ void RendererVulkan::CreateTextureRenderPass(){
|
|||
|
||||
const vk::AttachmentDescription color_attachment = {
|
||||
.format = vk::Format::eR16G16B16A16Sfloat,
|
||||
.samples = vk::SampleCountFlagBits::e1,
|
||||
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||
.initialLayout = vk::ImageLayout::eUndefined,
|
||||
.finalLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||
.finalLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||
};
|
||||
|
||||
vk::SubpassDependency dependency = {
|
||||
.srcSubpass = VK_SUBPASS_EXTERNAL,
|
||||
.dstSubpass = 0,
|
||||
.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
||||
.dstStageMask = vk::PipelineStageFlagBits::eFragmentShader,
|
||||
.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
};
|
||||
|
||||
const vk::RenderPassCreateInfo renderpass_info = {
|
||||
|
|
@ -259,8 +277,8 @@ void RendererVulkan::CreateTextureRenderPass(){
|
|||
.pAttachments = &color_attachment,
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = &subpass,
|
||||
.dependencyCount = 0,
|
||||
.pDependencies = nullptr,
|
||||
.dependencyCount = 1,
|
||||
.pDependencies = &dependency,
|
||||
};
|
||||
textureRenderpass = instance.GetDevice().createRenderPass(renderpass_info);
|
||||
}
|
||||
|
|
@ -285,7 +303,7 @@ void RendererVulkan::AllocateTexture(TextureInfo& texture, int width, int height
|
|||
.mipLevels = 1,
|
||||
.arrayLayers = 1,
|
||||
.samples = vk::SampleCountFlagBits::e1,
|
||||
.usage = vk::ImageUsageFlagBits::eSampled,
|
||||
.usage = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eColorAttachment,
|
||||
};
|
||||
|
||||
const VmaAllocationCreateInfo alloc_info = {
|
||||
|
|
@ -303,8 +321,10 @@ void RendererVulkan::AllocateTexture(TextureInfo& texture, int width, int height
|
|||
VkResult result = vmaCreateImage(instance.GetAllocator(), &unsafe_image_info, &alloc_info,
|
||||
&unsafe_image, &texture.allocation, nullptr);
|
||||
if (result != VK_SUCCESS) [[unlikely]] {
|
||||
LOG_CRITICAL(Render_Vulkan, "Failed allocating texture with error {}", result);
|
||||
LOG_CRITICAL(Render_Vulkan, "Failed allocating regular texture ({}x{}) with error {}", texture.width, texture.height, result);
|
||||
UNREACHABLE();
|
||||
} else {
|
||||
LOG_INFO(Render_Vulkan, "Successfully allocated regular texture");
|
||||
}
|
||||
texture.image = vk::Image{unsafe_image};
|
||||
|
||||
|
|
@ -327,14 +347,25 @@ void RendererVulkan::AllocateTexture(TextureInfo& texture, int width, int height
|
|||
|
||||
|
||||
void RendererVulkan::AllocatePPTextures(){
|
||||
int TopWidth = 400;
|
||||
int TopHeight = 240;
|
||||
int BottomWidth = 320;
|
||||
int BottomHeight = 240;
|
||||
|
||||
if (currTopTextureWidth != 0 && currBottomTextureWidth != 0 && currTopTextureHeight != 0 && currBottomTextureHeight != 0){
|
||||
TopWidth = currTopTextureWidth;
|
||||
TopHeight = currTopTextureHeight;
|
||||
BottomWidth = currBottomTextureWidth;
|
||||
BottomHeight = currBottomTextureHeight;
|
||||
}
|
||||
for (int i = 0; i < intermediateTextures[0].size(); i++){
|
||||
AllocateTexture(intermediateTextures[0][i], currTopTextureWidth, currTopTextureHeight, vk::Format::eR16G16B16A16Sfloat);
|
||||
AllocateTexture(intermediateTextures[0][i], TopWidth, TopHeight, vk::Format::eR16G16B16A16Sfloat);
|
||||
}
|
||||
for (int i = 0; i < intermediateTextures[1].size(); i++){
|
||||
AllocateTexture(intermediateTextures[1][i], currBottomTextureWidth, currBottomTextureHeight, vk::Format::eR16G16B16A16Sfloat);
|
||||
AllocateTexture(intermediateTextures[1][i], BottomWidth, BottomHeight, vk::Format::eR16G16B16A16Sfloat);
|
||||
}
|
||||
AllocateTexture(antialiasTextures[0], currTopTextureWidth, currTopTextureHeight, vk::Format::eR16G16B16A16Sfloat);
|
||||
AllocateTexture(antialiasTextures[1], currBottomTextureWidth, currBottomTextureHeight, vk::Format::eR16G16B16A16Sfloat);
|
||||
AllocateTexture(antialiasTextures[0], TopWidth, TopHeight, vk::Format::eR16G16B16A16Sfloat);
|
||||
AllocateTexture(antialiasTextures[1], BottomWidth, BottomHeight, vk::Format::eR16G16B16A16Sfloat);
|
||||
};
|
||||
|
||||
void RendererVulkan::CreateTextureFramebuffer(TextureInfo& texture, vk::Framebuffer& framebuffer) {
|
||||
|
|
@ -360,18 +391,137 @@ void RendererVulkan::CreatePPTextureFramebuffers(){
|
|||
}
|
||||
};
|
||||
|
||||
void RendererVulkan::PrepareDraw(Frame* frame, const Layout::FramebufferLayout& layout) {
|
||||
const auto sampler = present_samplers[Settings::values.filter_mode.GetValue()];
|
||||
void RendererVulkan::PrepareTextureDraw(TextureInfo framebufferTexture, vk::Framebuffer framebuffer, vk::Pipeline shaderPipeline, std::vector<TextureInfo> texturesToSample, int filterMode){
|
||||
const auto sampler = present_samplers[filterMode];
|
||||
const auto present_set = present_heap.Commit();
|
||||
for (u32 index = 0; index < screen_infos.size(); index++) {
|
||||
update_queue.AddImageSampler(present_set, 0, index, screen_infos[index].image_view,
|
||||
sampler);
|
||||
for (u32 i = 0; i < texturesToSample.size(); i++) {
|
||||
update_queue.AddImageSampler(present_set, i, 0, texturesToSample[i].image_view, sampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
}
|
||||
|
||||
renderpass_cache.EndRendering();
|
||||
scheduler.Record([this, framebufferTexture, framebuffer, shaderPipeline, present_set](vk::CommandBuffer cmdbuf) {
|
||||
const vk::Viewport viewport = {
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = static_cast<float>(framebufferTexture.width),
|
||||
.height = static_cast<float>(framebufferTexture.height),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
|
||||
const vk::Rect2D scissor = {
|
||||
.offset = {0, 0},
|
||||
.extent = {framebufferTexture.width, framebufferTexture.height},
|
||||
};
|
||||
|
||||
const vk::ClearColorValue clear_color = {
|
||||
.float32 =
|
||||
std::array{
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
},
|
||||
};
|
||||
cmdbuf.setViewport(0, viewport);
|
||||
cmdbuf.setScissor(0, scissor);
|
||||
|
||||
const vk::ClearValue clear{.color = clear_color};
|
||||
const vk::PipelineLayout layout{*present_pipeline_layout};
|
||||
const vk::RenderPassBeginInfo renderpass_begin_info = {
|
||||
.renderPass = textureRenderpass,
|
||||
.framebuffer = framebuffer,
|
||||
.renderArea =
|
||||
vk::Rect2D{
|
||||
.offset = {0, 0},
|
||||
.extent = {framebufferTexture.width, framebufferTexture.height},
|
||||
},
|
||||
.clearValueCount = 1,
|
||||
.pClearValues = &clear,
|
||||
};
|
||||
const std::array<float, 4> blendConstants = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
cmdbuf.setBlendConstants(blendConstants.data());
|
||||
cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
||||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, shaderPipeline);
|
||||
cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, layout, 0, present_set, {});
|
||||
});
|
||||
}
|
||||
|
||||
void RendererVulkan::PrepareTextureDrawFromScreenInfo(TextureInfo framebufferTexture, vk::Framebuffer framebuffer, vk::Pipeline shaderPipeline, std::vector<u32> screenids, int filterMode){
|
||||
const auto sampler = present_samplers[filterMode];
|
||||
const auto present_set = present_heap.Commit();
|
||||
for (u32 i = 0; i < screenids.size(); i++) {
|
||||
update_queue.AddImageSampler(present_set, i, 0, screen_infos[screenids[i]].image_view,
|
||||
sampler, vk::ImageLayout::eGeneral);
|
||||
}
|
||||
|
||||
renderpass_cache.EndRendering();
|
||||
scheduler.Record([this, framebufferTexture, framebuffer, shaderPipeline, present_set](vk::CommandBuffer cmdbuf) {
|
||||
const vk::Viewport viewport = {
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = static_cast<float>(framebufferTexture.width),
|
||||
.height = static_cast<float>(framebufferTexture.height),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
|
||||
const vk::Rect2D scissor = {
|
||||
.offset = {0, 0},
|
||||
.extent = {framebufferTexture.width, framebufferTexture.height},
|
||||
};
|
||||
|
||||
const vk::ClearColorValue clear_color = {
|
||||
.float32 =
|
||||
std::array{
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f,
|
||||
},
|
||||
};
|
||||
cmdbuf.setViewport(0, viewport);
|
||||
cmdbuf.setScissor(0, scissor);
|
||||
|
||||
const vk::ClearValue clear{.color = clear_color};
|
||||
const vk::PipelineLayout layout{*present_pipeline_layout};
|
||||
const vk::RenderPassBeginInfo renderpass_begin_info = {
|
||||
.renderPass = textureRenderpass,
|
||||
.framebuffer = framebuffer,
|
||||
.renderArea =
|
||||
vk::Rect2D{
|
||||
.offset = {0, 0},
|
||||
.extent = {framebufferTexture.width, framebufferTexture.height},
|
||||
},
|
||||
.clearValueCount = 1,
|
||||
.pClearValues = &clear,
|
||||
};
|
||||
const std::array<float, 4> blendConstants = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
cmdbuf.setBlendConstants(blendConstants.data());
|
||||
cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
||||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, shaderPipeline);
|
||||
cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, layout, 0, present_set, {});
|
||||
});
|
||||
}
|
||||
|
||||
void RendererVulkan::PrepareDrawFromScreenInfo(Frame* frame, const Layout::FramebufferLayout& layout, vk::Pipeline shaderPipeline, std::vector<u32> screenids, int filterMode) {
|
||||
const auto sampler = present_samplers[filterMode];
|
||||
const auto present_set = present_heap.Commit();
|
||||
for (u32 i = 0; i < screenids.size(); i++) {
|
||||
update_queue.AddImageSampler(present_set, i, 0, screen_infos[screenids[i]].image_view,
|
||||
sampler, vk::ImageLayout::eGeneral);
|
||||
}
|
||||
|
||||
renderpass_cache.EndRendering();
|
||||
vk::RenderPass currentRenderPass;
|
||||
if (clearingColorAttachment){
|
||||
currentRenderPass = main_present_window.Renderpass();
|
||||
} else {
|
||||
currentRenderPass = main_present_window.LoadRenderpass();
|
||||
}
|
||||
scheduler.Record([this, layout, frame, present_set,
|
||||
renderpass = main_present_window.Renderpass(),
|
||||
index = current_pipeline](vk::CommandBuffer cmdbuf) {
|
||||
currentRenderPass,
|
||||
shaderPipeline](vk::CommandBuffer cmdbuf) {
|
||||
const vk::Viewport viewport = {
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
|
|
@ -392,7 +542,7 @@ void RendererVulkan::PrepareDraw(Frame* frame, const Layout::FramebufferLayout&
|
|||
const vk::ClearValue clear{.color = clear_color};
|
||||
const vk::PipelineLayout layout{*present_pipeline_layout};
|
||||
const vk::RenderPassBeginInfo renderpass_begin_info = {
|
||||
.renderPass = renderpass,
|
||||
.renderPass = currentRenderPass,
|
||||
.framebuffer = frame->framebuffer,
|
||||
.renderArea =
|
||||
vk::Rect2D{
|
||||
|
|
@ -402,12 +552,68 @@ void RendererVulkan::PrepareDraw(Frame* frame, const Layout::FramebufferLayout&
|
|||
.clearValueCount = 1,
|
||||
.pClearValues = &clear,
|
||||
};
|
||||
const std::array<float, 4> blendConstants = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
cmdbuf.setBlendConstants(blendConstants.data());
|
||||
cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
||||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, present_pipelines[index]);
|
||||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, shaderPipeline);
|
||||
cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, layout, 0, present_set, {});
|
||||
});
|
||||
}
|
||||
|
||||
void RendererVulkan::PrepareDrawFromTextureInfo(Frame* frame, const Layout::FramebufferLayout& layout, vk::Pipeline shaderPipeline, std::vector<TextureInfo> texturesToSample, int filterMode) {
|
||||
const auto sampler = present_samplers[filterMode];
|
||||
const auto present_set = present_heap.Commit();
|
||||
for (u32 i = 0; i < texturesToSample.size(); i++) {
|
||||
update_queue.AddImageSampler(present_set, i, 0, texturesToSample[i].image_view, sampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
}
|
||||
|
||||
renderpass_cache.EndRendering();
|
||||
vk::RenderPass currentRenderPass;
|
||||
if (clearingColorAttachment){
|
||||
currentRenderPass = main_present_window.Renderpass();
|
||||
} else {
|
||||
currentRenderPass = main_present_window.LoadRenderpass();
|
||||
}
|
||||
scheduler.Record([this, layout, frame, present_set,
|
||||
currentRenderPass,
|
||||
shaderPipeline](vk::CommandBuffer cmdbuf) {
|
||||
const vk::Viewport viewport = {
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = static_cast<float>(layout.width),
|
||||
.height = static_cast<float>(layout.height),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
|
||||
const vk::Rect2D scissor = {
|
||||
.offset = {0, 0},
|
||||
.extent = {layout.width, layout.height},
|
||||
};
|
||||
|
||||
cmdbuf.setViewport(0, viewport);
|
||||
cmdbuf.setScissor(0, scissor);
|
||||
|
||||
const vk::ClearValue clear{.color = clear_color};
|
||||
const vk::PipelineLayout layout{*present_pipeline_layout};
|
||||
const vk::RenderPassBeginInfo renderpass_begin_info = {
|
||||
.renderPass = currentRenderPass,
|
||||
.framebuffer = frame->framebuffer,
|
||||
.renderArea =
|
||||
vk::Rect2D{
|
||||
.offset = {0, 0},
|
||||
.extent = {frame->width, frame->height},
|
||||
},
|
||||
.clearValueCount = 1,
|
||||
.pClearValues = &clear,
|
||||
};
|
||||
const std::array<float, 4> blendConstants = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
cmdbuf.setBlendConstants(blendConstants.data());
|
||||
cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
|
||||
cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, shaderPipeline);
|
||||
cmdbuf.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, layout, 0, present_set, {});
|
||||
});
|
||||
}
|
||||
void RendererVulkan::RenderToWindow(PresentWindow& window, const Layout::FramebufferLayout& layout,
|
||||
bool flipped) {
|
||||
Frame* frame = window.GetRenderFrame();
|
||||
|
|
@ -935,7 +1141,7 @@ void RendererVulkan::ConfigureFramebufferTexture(TextureInfo& texture,
|
|||
VkResult result = vmaCreateImage(instance.GetAllocator(), &unsafe_image_info, &alloc_info,
|
||||
&unsafe_image, &texture.allocation, nullptr);
|
||||
if (result != VK_SUCCESS) [[unlikely]] {
|
||||
LOG_CRITICAL(Render_Vulkan, "Failed allocating texture with error {}", result);
|
||||
LOG_CRITICAL(Render_Vulkan, "Failed allocating framebuffer texture with error {}", result);
|
||||
UNREACHABLE();
|
||||
}
|
||||
texture.image = vk::Image{unsafe_image};
|
||||
|
|
@ -983,7 +1189,7 @@ void RendererVulkan::FillScreen(Common::Vec3<u8> color, const TextureInfo& textu
|
|||
const vk::ImageMemoryBarrier pre_barrier = {
|
||||
.srcAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
|
||||
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.oldLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
|
|
@ -995,7 +1201,7 @@ void RendererVulkan::FillScreen(Common::Vec3<u8> color, const TextureInfo& textu
|
|||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
|
||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
|
|
@ -1034,19 +1240,19 @@ void RendererVulkan::DrawSingleScreen(u32 screen_id, float screenLeft, float scr
|
|||
Layout::DisplayOrientation orientation) {
|
||||
const ScreenInfo& screen_info = screen_infos[screen_id];
|
||||
const auto& texcoords = screen_info.texcoords;
|
||||
|
||||
const u32 scale_factor = GetResolutionScaleFactor();
|
||||
// Texture Width and Height when correctly rotated to landscape
|
||||
float textureWidth = static_cast<float>(screen_info.texture.height * scale_factor);
|
||||
float textureHeight = static_cast<float>(screen_info.texture.width * scale_factor);
|
||||
|
||||
// Texture Width and Height when correctly rotated to landscape
|
||||
bool isDownsampling = false;
|
||||
int scalingMode; //0 is Nearest Neighbor, 1 is Gamma Corrected Bilinear, 2 is High Quality Scaling (Upsampling via Gamma Corrected Bilinear, Downsampling is Gamma Corrected Area Sampling)
|
||||
if (Settings::values.filter_mode.GetValue()){
|
||||
scalingMode = 2;
|
||||
int currentScreen;
|
||||
if (textureWidth == currTopTextureWidth && textureHeight == currTopTextureHeight){
|
||||
currentScreen = 0;
|
||||
} else {
|
||||
scalingMode = 0;
|
||||
currentScreen = 1;
|
||||
}
|
||||
bool isDownsampling = false;
|
||||
int scalingMode; //0 is Nearest Neighbor, 1 is Gamma Corrected Bilinear, 2 is Adaptive (Bilinear/Area), 3 is FSR, 4 is Sharp Bilinear
|
||||
scalingMode = static_cast<int>(Settings::values.output_scaling.GetValue());
|
||||
int antialiasingMode = static_cast<int>(Settings::values.antialiasing_filter.GetValue()); //0 is none, 1 is FXAA, 2 is SMAA
|
||||
if (orientation == Layout::DisplayOrientation::Landscape || orientation == Layout::DisplayOrientation::LandscapeFlipped) {
|
||||
if (textureWidth > screenWidth){
|
||||
|
|
@ -1060,19 +1266,18 @@ void RendererVulkan::DrawSingleScreen(u32 screen_id, float screenLeft, float scr
|
|||
// Rotate Internal Texture to Landscape (The 3DS stores images rotated 90° internally)
|
||||
std::array<ScreenRectVertex, 4> rotate_vertices;
|
||||
rotate_vertices = {{
|
||||
ScreenRectVertex(-1.f, 1.f, texcoords.bottom, texcoords.left), //Left, Top
|
||||
ScreenRectVertex(1.f, 1.f, texcoords.bottom, texcoords.right), //Right, Top
|
||||
ScreenRectVertex(-1.f, -1.f, texcoords.top, texcoords.left), //Left, Bottom
|
||||
ScreenRectVertex(1.f, -1.f, texcoords.top, texcoords.right), //Right, Bottom
|
||||
ScreenRectVertex(-1.f, 1.f, texcoords.top, texcoords.left), //Left, Top
|
||||
ScreenRectVertex(1.f, 1.f, texcoords.top, texcoords.right), //Right, Top
|
||||
ScreenRectVertex(-1.f, -1.f, texcoords.bottom, texcoords.left), //Left, Bottom
|
||||
ScreenRectVertex(1.f, -1.f, texcoords.bottom, texcoords.right), //Right, Bottom
|
||||
}};
|
||||
|
||||
// Vertices for 1:1 Texture Mapping.
|
||||
std::array<ScreenRectVertex, 4> pass_through_vertices;
|
||||
pass_through_vertices = {{
|
||||
ScreenRectVertex(-1.f, 1.f, 0.f, 1.f), //Left, Top
|
||||
ScreenRectVertex(1.f, 1.f, 1.f, 1.f), //Right, Top
|
||||
ScreenRectVertex(-1.f, -1.f, 0.f, 0.f), //Left, Bottom
|
||||
ScreenRectVertex(1.f, -1.f, 1.f, 0.f), //Right, Bottom
|
||||
ScreenRectVertex(-1.f, 1.f, 0.f, 0.f), //Left, Top
|
||||
ScreenRectVertex(1.f, 1.f, 1.f, 0.f), //Right, Top
|
||||
ScreenRectVertex(-1.f, -1.f, 0.f, 1.f), //Left, Bottom
|
||||
ScreenRectVertex(1.f, -1.f, 1.f, 1.f), //Right, Bottom
|
||||
}};
|
||||
|
||||
// Vertices for Azahar's Output Layout
|
||||
|
|
@ -1080,71 +1285,120 @@ void RendererVulkan::DrawSingleScreen(u32 screen_id, float screenLeft, float scr
|
|||
switch (orientation) {
|
||||
case Layout::DisplayOrientation::Landscape:
|
||||
output_vertices = {{
|
||||
ScreenRectVertex(screenLeft, screenTop, 0.f, 1.f), //Left, Top
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop, 1.f, 1.f), //Right, Top
|
||||
ScreenRectVertex(screenLeft, screenTop + screenHeight, 0.f, 0.f), //Left, Bottom
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop + screenHeight, 1.f, 0.f), //Right, Bottom
|
||||
ScreenRectVertex(screenLeft, screenTop, 0.f, 0.f),
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop, 1.f, 0.f),
|
||||
ScreenRectVertex(screenLeft, screenTop + screenHeight, 0.f, 1.f),
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop + screenHeight, 1.f, 1.f),
|
||||
}};
|
||||
break;
|
||||
case Layout::DisplayOrientation::Portrait:
|
||||
output_vertices = {{
|
||||
ScreenRectVertex(screenLeft, screenTop, 1.f, 1.f), //Left, Top
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop, 1.f, 0.f), //Right, Top
|
||||
ScreenRectVertex(screenLeft, screenTop + screenHeight, 0.f, 1.f), //Left, Bottom
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop + screenHeight, 0.f, 0.f), //Right, Bottom
|
||||
ScreenRectVertex(screenLeft, screenTop, 1.f, 0.f),
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop, 1.f, 1.f),
|
||||
ScreenRectVertex(screenLeft, screenTop + screenHeight, 0.f, 0.f),
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop + screenHeight, 0.f, 1.f),
|
||||
}};
|
||||
std::swap(screenHeight, screenWidth);
|
||||
break;
|
||||
case Layout::DisplayOrientation::LandscapeFlipped:
|
||||
output_vertices = {{
|
||||
ScreenRectVertex(screenLeft, screenTop, 0.f, 0.f), //Left, Top
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop, 1.f, 0.f), //Right, Top
|
||||
ScreenRectVertex(screenLeft, screenTop + screenHeight, 0.f, 1.f), //Left, Bottom
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop + screenHeight, 1.f, 1.f), //Right, Bottom
|
||||
ScreenRectVertex(screenLeft, screenTop, 0.f, 1.f),
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop, 1.f, 1.f),
|
||||
ScreenRectVertex(screenLeft, screenTop + screenHeight, 0.f, 0.f),
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop + screenHeight, 1.f, 0.f),
|
||||
}};
|
||||
break;
|
||||
case Layout::DisplayOrientation::PortraitFlipped:
|
||||
output_vertices = {{
|
||||
ScreenRectVertex(screenLeft, screenTop, 0.f, 0.f), //Left, Top
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop, 0.f, 1.f), //Right, Top
|
||||
ScreenRectVertex(screenLeft, screenTop + screenHeight, 1.f, 0.f), //Left, Bottom
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop + screenHeight, 1.f, 1.f), //Right, Bottom
|
||||
ScreenRectVertex(screenLeft, screenTop, 0.f, 1.f),
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop, 0.f, 0.f),
|
||||
ScreenRectVertex(screenLeft, screenTop + screenHeight, 1.f, 1.f),
|
||||
ScreenRectVertex(screenLeft + screenWidth, screenTop + screenHeight, 1.f, 0.f),
|
||||
}};
|
||||
std::swap(screenHeight, screenWidth);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Render_OpenGL, "Unknown DisplayOrientation: {}", orientation);
|
||||
break;
|
||||
}
|
||||
const u64 size = sizeof(ScreenRectVertex) * output_vertices.size();
|
||||
auto [data, offset, invalidate] = vertex_buffer.Map(size, 16);
|
||||
std::memcpy(data, output_vertices.data(), size);
|
||||
vertex_buffer.Commit(size);
|
||||
|
||||
draw_info.i_resolution =
|
||||
Common::MakeVec(static_cast<f32>(screen_info.texture.width * scale_factor),
|
||||
static_cast<f32>(screen_info.texture.height * scale_factor),
|
||||
1.0f / static_cast<f32>(screen_info.texture.width * scale_factor),
|
||||
1.0f / static_cast<f32>(screen_info.texture.height * scale_factor));
|
||||
draw_info.o_resolution = Common::MakeVec(screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight);
|
||||
draw_info.screen_id_l = screen_id;
|
||||
int passes = 5;
|
||||
std::vector<VertexBufferPointer> vertexBufferPointers(passes);
|
||||
for (auto& vbp : vertexBufferPointers){
|
||||
std::tie(vbp.data, vbp.offset, vbp.invalidate) = vertex_buffer.Map(size, 16);
|
||||
vertex_buffer.Commit(size);
|
||||
}
|
||||
std::vector<PresentUniformData> drawInfos(passes);
|
||||
for (auto& info : drawInfos){
|
||||
info = draw_info;
|
||||
}
|
||||
|
||||
scheduler.Record([this, offset = offset, info = draw_info](vk::CommandBuffer cmdbuf) {
|
||||
const u32 first_vertex = static_cast<u32>(offset) / sizeof(ScreenRectVertex);
|
||||
// Attempted Multipass
|
||||
std::vector<u32> screen_ids = {screen_id};
|
||||
PrepareTextureDrawFromScreenInfo(intermediateTextures[currentScreen][0], intermediateTextureFBOs[currentScreen][0], post_pipelines_texture[0], screen_ids, 1);
|
||||
UpdateVertexBuffer(rotate_vertices, vertexBufferPointers[0]);
|
||||
drawInfos[0].convert_colors = 1;
|
||||
Draw(vertexBufferPointers[0], drawInfos[0]);
|
||||
|
||||
std::vector<TextureInfo> texturesToSample = {intermediateTextures[currentScreen][0]};
|
||||
PrepareDrawFromTextureInfo(currentFrame, currentFramebufferLayout, present_pipelines[current_pipeline], texturesToSample, 1);
|
||||
ApplySecondLayerOpacity();
|
||||
UpdateVertexBuffer(output_vertices, vertexBufferPointers[1]);
|
||||
drawInfos[1].convert_colors = 2;
|
||||
Draw(vertexBufferPointers[1], drawInfos[1]);
|
||||
}
|
||||
|
||||
|
||||
void RendererVulkan::UpdateVertexBuffer(std::array<ScreenRectVertex, 4> vertices, VertexBufferPointer vbp){
|
||||
const u64 size = sizeof(ScreenRectVertex) * vertices.size();
|
||||
std::memcpy(vbp.data, vertices.data(), size);
|
||||
}
|
||||
|
||||
void RendererVulkan::Draw(VertexBufferPointer vbp, PresentUniformData pushconstant){
|
||||
scheduler.Record([this, vbp, pushconstant](vk::CommandBuffer cmdbuf) {
|
||||
const u32 first_vertex = static_cast<u32>(vbp.offset) / sizeof(ScreenRectVertex);
|
||||
cmdbuf.pushConstants(*present_pipeline_layout,
|
||||
vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eVertex,
|
||||
0, sizeof(info), &info);
|
||||
|
||||
0, sizeof(pushconstant), &pushconstant);
|
||||
cmdbuf.bindVertexBuffers(0, vertex_buffer.Handle(), {0});
|
||||
cmdbuf.draw(4, 1, first_vertex, 0);
|
||||
cmdbuf.endRenderPass();
|
||||
});
|
||||
}
|
||||
|
||||
void RendererVulkan::ApplySecondLayerOpacity() {
|
||||
float alpha;
|
||||
if (applyingOpacity){
|
||||
if (drawingPrimaryScreen){
|
||||
alpha = 1.0;
|
||||
} else {
|
||||
if (usingTopOpacity){
|
||||
if (currentFramebufferLayout.top_opacity < 1) {
|
||||
alpha = currentFramebufferLayout.top_opacity;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (currentFramebufferLayout.bottom_opacity < 1) {
|
||||
alpha = currentFramebufferLayout.bottom_opacity;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
scheduler.Record([alpha](vk::CommandBuffer cmdbuf) {
|
||||
const std::array<float, 4> blend_constants = {0.0f, 0.0f, 0.0f, alpha};
|
||||
cmdbuf.setBlendConstants(blend_constants.data());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void RendererVulkan::DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, float x, float y,
|
||||
float w, float h,
|
||||
Layout::DisplayOrientation orientation) {
|
||||
const ScreenInfo& screen_info_l = screen_infos[screen_id_l];
|
||||
const auto& texcoords = screen_info_l.texcoords;
|
||||
const u32 scale_factor = GetResolutionScaleFactor();
|
||||
float textureWidth = static_cast<float>(screen_info_l.texture.height * scale_factor);
|
||||
float textureHeight = static_cast<float>(screen_info_l.texture.width * scale_factor);
|
||||
|
||||
std::array<ScreenRectVertex, 4> vertices;
|
||||
switch (orientation) {
|
||||
|
|
@ -1186,38 +1440,23 @@ void RendererVulkan::DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, fl
|
|||
LOG_ERROR(Render_Vulkan, "Unknown DisplayOrientation: {}", orientation);
|
||||
break;
|
||||
}
|
||||
|
||||
const u64 size = sizeof(ScreenRectVertex) * vertices.size();
|
||||
auto [data, offset, invalidate] = vertex_buffer.Map(size, 16);
|
||||
std::memcpy(data, vertices.data(), size);
|
||||
vertex_buffer.Commit(size);
|
||||
int passes = 1;
|
||||
std::vector<VertexBufferPointer> vertexBufferPointers(passes);
|
||||
for (auto& vbp : vertexBufferPointers){
|
||||
std::tie(vbp.data, vbp.offset, vbp.invalidate) = vertex_buffer.Map(size, 16);
|
||||
vertex_buffer.Commit(size);
|
||||
}
|
||||
|
||||
const u32 scale_factor = GetResolutionScaleFactor();
|
||||
draw_info.i_resolution =
|
||||
Common::MakeVec(static_cast<f32>(screen_info_l.texture.width * scale_factor),
|
||||
static_cast<f32>(screen_info_l.texture.height * scale_factor),
|
||||
1.0f / static_cast<f32>(screen_info_l.texture.width * scale_factor),
|
||||
1.0f / static_cast<f32>(screen_info_l.texture.height * scale_factor));
|
||||
draw_info.o_resolution = Common::MakeVec(h, w, 1.0f / h, 1.0f / w);
|
||||
std::vector<u32> screenids = {screen_id_l, screen_id_r};
|
||||
PrepareDrawFromScreenInfo(currentFrame, currentFramebufferLayout, present_pipelines[current_pipeline], screenids, 1);
|
||||
ApplySecondLayerOpacity(); // Apply the initial default opacity value; Needed to avoid flickering
|
||||
UpdateVertexBuffer(vertices, vertexBufferPointers[0]);
|
||||
draw_info.i_resolution = Common::MakeVec(static_cast<f32>(textureWidth), static_cast<f32>(textureHeight), 1.0f / static_cast<f32>(textureWidth), 1.0f / static_cast<f32>(textureHeight));
|
||||
draw_info.o_resolution = Common::MakeVec(w, h, 1.0f / w, 1.0f / h);
|
||||
draw_info.screen_id_l = screen_id_l;
|
||||
draw_info.screen_id_r = screen_id_r;
|
||||
|
||||
scheduler.Record([this, offset = offset, info = draw_info](vk::CommandBuffer cmdbuf) {
|
||||
const u32 first_vertex = static_cast<u32>(offset) / sizeof(ScreenRectVertex);
|
||||
cmdbuf.pushConstants(*present_pipeline_layout,
|
||||
vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eVertex,
|
||||
0, sizeof(info), &info);
|
||||
|
||||
cmdbuf.bindVertexBuffers(0, vertex_buffer.Handle(), {0});
|
||||
cmdbuf.draw(4, 1, first_vertex, 0);
|
||||
});
|
||||
}
|
||||
|
||||
void RendererVulkan::ApplySecondLayerOpacity(float alpha) {
|
||||
scheduler.Record([alpha](vk::CommandBuffer cmdbuf) {
|
||||
const std::array<float, 4> blend_constants = {0.0f, 0.0f, 0.0f, alpha};
|
||||
cmdbuf.setBlendConstants(blend_constants.data());
|
||||
});
|
||||
Draw(vertexBufferPointers[0], draw_info);
|
||||
}
|
||||
|
||||
void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
||||
|
|
@ -1246,6 +1485,7 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
|||
DrawSingleScreen(leftside, top_screen_left / 2, top_screen_top, top_screen_width / 2,
|
||||
top_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
clearingColorAttachment = false;
|
||||
DrawSingleScreen(rightside, static_cast<float>((top_screen_left / 2) + (layout.width / 2)),
|
||||
top_screen_top, top_screen_width / 2, top_screen_height, orientation);
|
||||
break;
|
||||
|
|
@ -1254,6 +1494,7 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
|||
DrawSingleScreen(leftside, top_screen_left, top_screen_top, top_screen_width,
|
||||
top_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
clearingColorAttachment = false;
|
||||
DrawSingleScreen(rightside, top_screen_left + layout.width / 2, top_screen_top,
|
||||
top_screen_width, top_screen_height, orientation);
|
||||
break;
|
||||
|
|
@ -1262,6 +1503,7 @@ void RendererVulkan::DrawTopScreen(const Layout::FramebufferLayout& layout,
|
|||
DrawSingleScreen(leftside, top_screen_left, top_screen_top, top_screen_width,
|
||||
top_screen_height, orientation);
|
||||
draw_info.layer = 1;
|
||||
clearingColorAttachment = false;
|
||||
DrawSingleScreen(
|
||||
rightside,
|
||||
static_cast<float>(layout.cardboard.top_screen_right_eye + (layout.width / 2)),
|
||||
|
|
@ -1347,33 +1589,49 @@ void RendererVulkan::DrawScreens(Frame* frame, const Layout::FramebufferLayout&
|
|||
ReloadPipeline(layout.render_3d_mode);
|
||||
}
|
||||
|
||||
PrepareDraw(frame, layout);
|
||||
// Track Texture Changes
|
||||
currTopTextureWidth = static_cast<float>(screen_infos[0].texture.height * GetResolutionScaleFactor());
|
||||
currTopTextureHeight = static_cast<float>(screen_infos[0].texture.width * GetResolutionScaleFactor());
|
||||
currBottomTextureWidth = static_cast<float>(screen_infos[2].texture.height * GetResolutionScaleFactor());
|
||||
currBottomTextureHeight = static_cast<float>(screen_infos[2].texture.width * GetResolutionScaleFactor());
|
||||
if (currTopTextureWidth != prevTopTextureWidth || currTopTextureHeight != prevTopTextureHeight || currBottomTextureWidth != prevBottomTextureWidth || currBottomTextureHeight != prevBottomTextureHeight){
|
||||
AllocatePPTextures();
|
||||
CreatePPTextureFramebuffers();
|
||||
LOG_INFO(Render_Vulkan, "PrevTopTexture Res: {}x{}, CurrTopTexture Res: {}x{}, PrevBottomTexture Res: {}x{}, CurrBottomTexture Res: {}x{}", prevTopTextureWidth, prevTopTextureHeight, currTopTextureWidth, currTopTextureHeight, prevBottomTextureWidth, prevBottomTextureHeight, currBottomTextureWidth, currBottomTextureHeight);
|
||||
}
|
||||
prevTopTextureWidth = currTopTextureWidth;
|
||||
prevTopTextureHeight = currTopTextureHeight;
|
||||
prevBottomTextureWidth = currBottomTextureWidth;
|
||||
prevBottomTextureHeight = currBottomTextureHeight;
|
||||
|
||||
currentFrame = frame;
|
||||
currentFramebufferLayout = layout;
|
||||
const auto& top_screen = layout.top_screen;
|
||||
const auto& bottom_screen = layout.bottom_screen;
|
||||
draw_info.modelview = MakeOrthographicMatrix(layout.width, layout.height);
|
||||
|
||||
draw_info.layer = 0;
|
||||
|
||||
// Apply the initial default opacity value; Needed to avoid flickering
|
||||
ApplySecondLayerOpacity(1.0f);
|
||||
|
||||
clearingColorAttachment = true;
|
||||
applyingOpacity = true;
|
||||
if (!Settings::values.swap_screen.GetValue()) {
|
||||
drawingPrimaryScreen = true;
|
||||
DrawTopScreen(layout, top_screen);
|
||||
draw_info.layer = 0;
|
||||
if (layout.bottom_opacity < 1) {
|
||||
ApplySecondLayerOpacity(layout.bottom_opacity);
|
||||
}
|
||||
drawingPrimaryScreen = false;
|
||||
usingTopOpacity = false;
|
||||
clearingColorAttachment = false;
|
||||
DrawBottomScreen(layout, bottom_screen);
|
||||
} else {
|
||||
drawingPrimaryScreen = true;
|
||||
DrawBottomScreen(layout, bottom_screen);
|
||||
draw_info.layer = 0;
|
||||
if (layout.top_opacity < 1) {
|
||||
ApplySecondLayerOpacity(layout.top_opacity);
|
||||
}
|
||||
drawingPrimaryScreen = false;
|
||||
usingTopOpacity = true;
|
||||
clearingColorAttachment = false;
|
||||
DrawTopScreen(layout, top_screen);
|
||||
}
|
||||
|
||||
applyingOpacity = false;
|
||||
if (layout.additional_screen_enabled) {
|
||||
const auto& additional_screen = layout.additional_screen;
|
||||
if (!Settings::values.swap_screen.GetValue()) {
|
||||
|
|
@ -1383,9 +1641,8 @@ void RendererVulkan::DrawScreens(Frame* frame, const Layout::FramebufferLayout&
|
|||
}
|
||||
}
|
||||
|
||||
DrawCursor(layout);
|
||||
|
||||
scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.endRenderPass(); });
|
||||
// Needs to be fixed
|
||||
// DrawCursor(layout);
|
||||
}
|
||||
|
||||
void RendererVulkan::DrawCursor(const Layout::FramebufferLayout& layout) {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,21 @@ struct TextureInfo {
|
|||
VmaAllocation allocation;
|
||||
};
|
||||
|
||||
struct ScreenRectVertex {
|
||||
ScreenRectVertex() = default;
|
||||
ScreenRectVertex(float x, float y, float u, float v)
|
||||
: position{Common::MakeVec(x, y)}, tex_coord{Common::MakeVec(u, v)} {}
|
||||
|
||||
Common::Vec2f position;
|
||||
Common::Vec2f tex_coord;
|
||||
};
|
||||
|
||||
struct VertexBufferPointer {
|
||||
unsigned char* data;
|
||||
unsigned int offset;
|
||||
bool invalidate;
|
||||
};
|
||||
|
||||
struct ScreenInfo {
|
||||
TextureInfo texture;
|
||||
Common::Rectangle<f32> texcoords;
|
||||
|
|
@ -63,11 +78,8 @@ struct PresentUniformData {
|
|||
int layer = 0;
|
||||
int reverse_interlaced = 0;
|
||||
int convert_colors;
|
||||
int areatex;
|
||||
int searchtex;
|
||||
int smaa_input;
|
||||
};
|
||||
static_assert(sizeof(PresentUniformData) == 128,
|
||||
static_assert(sizeof(PresentUniformData) == 116,
|
||||
"PresentUniformData does not structure in shader!");
|
||||
|
||||
class RendererVulkan : public VideoCore::RendererBase {
|
||||
|
|
@ -101,8 +113,18 @@ private:
|
|||
void RenderScreenshot();
|
||||
void RenderScreenshotWithStagingCopy();
|
||||
bool TryRenderScreenshotWithHostMemory();
|
||||
void PrepareDraw(Frame* frame, const Layout::FramebufferLayout& layout);
|
||||
void PrepareTextureDraw(TextureInfo& textureInfo, vk::Pipeline& pipeline, int filterMode, std::vector<vk::ImageView> imageViews);
|
||||
// Sets up command buffer for sampling from a screen_info to the screen framebuffer
|
||||
void PrepareDrawFromScreenInfo(Frame* frame, const Layout::FramebufferLayout& layout, vk::Pipeline shaderPipeline, std::vector<u32> screenids, int filterMode);
|
||||
// Sets up command buffer for sampling from a texture to the screen framebuffer
|
||||
void PrepareDrawFromTextureInfo(Frame* frame, const Layout::FramebufferLayout& layout, vk::Pipeline shaderPipeline, std::vector<TextureInfo> texturesToSample, int filterMode);
|
||||
// Sets up command buffer for sampling from a texture to an intermediate texture framebuffer
|
||||
void PrepareTextureDraw(TextureInfo framebufferTexture, vk::Framebuffer framebuffer, vk::Pipeline shaderPipeline, std::vector<TextureInfo> texturesToSample, int filterMode);
|
||||
// Sets up command buffer for sampling from a screen_info to an intermediate texture framebuffer
|
||||
void PrepareTextureDrawFromScreenInfo(TextureInfo framebufferTexture, vk::Framebuffer framebuffer, vk::Pipeline shaderPipeline, std::vector<u32> screenids, int filterMode);
|
||||
|
||||
|
||||
void UpdateVertexBuffer(std::array<ScreenRectVertex, 4> vertices, VertexBufferPointer vbp);
|
||||
void Draw(VertexBufferPointer vbp, PresentUniformData pushconstant);
|
||||
void RenderToWindow(PresentWindow& window, const Layout::FramebufferLayout& layout,
|
||||
bool flipped);
|
||||
|
||||
|
|
@ -117,7 +139,7 @@ private:
|
|||
void DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, float x, float y, float w,
|
||||
float h, Layout::DisplayOrientation orientation);
|
||||
|
||||
void ApplySecondLayerOpacity(float alpha);
|
||||
void ApplySecondLayerOpacity();
|
||||
|
||||
void DrawCursor(const Layout::FramebufferLayout& layout);
|
||||
|
||||
|
|
@ -135,7 +157,6 @@ private:
|
|||
// Create Framebuffers that are attached to the Post Processing Textures
|
||||
void CreatePPTextureFramebuffers();
|
||||
void AllocateSMAATextures();
|
||||
|
||||
private:
|
||||
Memory::MemorySystem& memory;
|
||||
Pica::PicaCore& pica;
|
||||
|
|
@ -193,12 +214,21 @@ private:
|
|||
// Array of framebuffer objects. 0 is top screen, 1 is bottom screen.
|
||||
std::array<std::array<vk::Framebuffer, 5>, 2> intermediateTextureFBOs;
|
||||
std::array<vk::Framebuffer, 2 > antialiasTextureFBOs;
|
||||
int currTopTextureWidth;
|
||||
int currTopTextureHeight;
|
||||
int currBottomTextureWidth;
|
||||
int currBottomTextureHeight;
|
||||
float currTopTextureWidth;
|
||||
float currTopTextureHeight;
|
||||
float currBottomTextureWidth;
|
||||
float currBottomTextureHeight;
|
||||
float prevTopTextureWidth;
|
||||
float prevTopTextureHeight;
|
||||
float prevBottomTextureWidth;
|
||||
float prevBottomTextureHeight;
|
||||
u32 current_pipeline = 0;
|
||||
|
||||
Frame* currentFrame;
|
||||
Layout::FramebufferLayout currentFramebufferLayout;
|
||||
bool clearingColorAttachment = true;
|
||||
bool applyingOpacity = true;
|
||||
bool drawingPrimaryScreen = false;
|
||||
bool usingTopOpacity = false;
|
||||
std::array<ScreenInfo, 3> screen_infos{};
|
||||
PresentUniformData draw_info{};
|
||||
vk::ClearColorValue clear_color{};
|
||||
|
|
|
|||
|
|
@ -318,7 +318,6 @@ vk::UniqueInstance CreateInstance(const Common::DynamicLibrary& library,
|
|||
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||
.apiVersion = TargetVulkanApiVersion,
|
||||
};
|
||||
|
||||
boost::container::static_vector<const char*, 2> layers;
|
||||
if (enable_validation) {
|
||||
layers.push_back("VK_LAYER_KHRONOS_validation");
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ PresentWindow::PresentWindow(Frontend::EmuWindow& emu_window_, const Instance& i
|
|||
surface{CreateSurface(instance.GetInstance(), emu_window)}, next_surface{surface},
|
||||
swapchain{instance, emu_window.GetFramebufferLayout().width,
|
||||
emu_window.GetFramebufferLayout().height, surface, low_refresh_rate_},
|
||||
graphics_queue{instance.GetGraphicsQueue()}, present_renderpass{CreateRenderpass()},
|
||||
graphics_queue{instance.GetGraphicsQueue()}, present_renderpass{CreateRenderpass()}, present_load_renderpass{CreateLoadRenderpass()},
|
||||
vsync_enabled{Settings::values.use_vsync.GetValue()},
|
||||
blit_supported{
|
||||
CanBlitToSwapchain(instance.GetPhysicalDevice(), swapchain.GetSurfaceFormat().format)},
|
||||
|
|
@ -157,6 +157,7 @@ PresentWindow::~PresentWindow() {
|
|||
const vk::Device device = instance.GetDevice();
|
||||
device.destroyCommandPool(command_pool);
|
||||
device.destroyRenderPass(present_renderpass);
|
||||
device.destroyRenderPass(present_load_renderpass);
|
||||
for (auto& frame : swap_chain) {
|
||||
device.destroyImageView(frame.image_view);
|
||||
device.destroyFramebuffer(frame.framebuffer);
|
||||
|
|
@ -512,16 +513,72 @@ vk::RenderPass PresentWindow::CreateRenderpass() {
|
|||
.finalLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||
};
|
||||
|
||||
const vk::SubpassDependency dependency = {
|
||||
.srcSubpass = VK_SUBPASS_EXTERNAL,
|
||||
.dstSubpass = 0,
|
||||
.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
||||
.dstStageMask = vk::PipelineStageFlagBits::eFragmentShader,
|
||||
.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
};
|
||||
|
||||
const vk::RenderPassCreateInfo renderpass_info = {
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &color_attachment,
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = &subpass,
|
||||
.dependencyCount = 0,
|
||||
.pDependencies = nullptr,
|
||||
.dependencyCount = 1,
|
||||
.pDependencies = &dependency,
|
||||
};
|
||||
|
||||
return instance.GetDevice().createRenderPass(renderpass_info);
|
||||
}
|
||||
|
||||
vk::RenderPass PresentWindow::CreateLoadRenderpass() {
|
||||
const vk::AttachmentReference color_ref = {
|
||||
.attachment = 0,
|
||||
.layout = vk::ImageLayout::eGeneral,
|
||||
};
|
||||
|
||||
const vk::SubpassDescription subpass = {
|
||||
.pipelineBindPoint = vk::PipelineBindPoint::eGraphics,
|
||||
.inputAttachmentCount = 0,
|
||||
.pInputAttachments = nullptr,
|
||||
.colorAttachmentCount = 1u,
|
||||
.pColorAttachments = &color_ref,
|
||||
.pResolveAttachments = 0,
|
||||
.pDepthStencilAttachment = nullptr,
|
||||
};
|
||||
|
||||
const vk::AttachmentDescription color_attachment = {
|
||||
.format = swapchain.GetSurfaceFormat().format,
|
||||
.samples = vk::SampleCountFlagBits::e1,
|
||||
.loadOp = vk::AttachmentLoadOp::eLoad,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.stencilLoadOp = vk::AttachmentLoadOp::eDontCare,
|
||||
.stencilStoreOp = vk::AttachmentStoreOp::eDontCare,
|
||||
.initialLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||
.finalLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||
};
|
||||
|
||||
const vk::SubpassDependency dependency = {
|
||||
.srcSubpass = VK_SUBPASS_EXTERNAL,
|
||||
.dstSubpass = 0,
|
||||
.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
||||
.dstStageMask = vk::PipelineStageFlagBits::eFragmentShader,
|
||||
.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
};
|
||||
|
||||
const vk::RenderPassCreateInfo renderpass_info = {
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &color_attachment,
|
||||
.subpassCount = 1,
|
||||
.pSubpasses = &subpass,
|
||||
.dependencyCount = 1,
|
||||
.pDependencies = &dependency,
|
||||
};
|
||||
|
||||
return instance.GetDevice().createRenderPass(renderpass_info);
|
||||
}
|
||||
} // namespace Vulkan
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ public:
|
|||
[[nodiscard]] vk::RenderPass Renderpass() const noexcept {
|
||||
return present_renderpass;
|
||||
}
|
||||
// Returns Renderpass that doesn't clear the image
|
||||
[[nodiscard]] vk::RenderPass LoadRenderpass() const noexcept {
|
||||
return present_load_renderpass;
|
||||
}
|
||||
|
||||
u32 ImageCount() const noexcept {
|
||||
return swapchain.GetImageCount();
|
||||
|
|
@ -69,7 +73,7 @@ private:
|
|||
void CopyToSwapchain(Frame* frame);
|
||||
|
||||
vk::RenderPass CreateRenderpass();
|
||||
|
||||
vk::RenderPass CreateLoadRenderpass();
|
||||
private:
|
||||
Frontend::EmuWindow& emu_window;
|
||||
const Instance& instance;
|
||||
|
|
@ -81,6 +85,7 @@ private:
|
|||
vk::CommandPool command_pool;
|
||||
vk::Queue graphics_queue;
|
||||
vk::RenderPass present_renderpass;
|
||||
vk::RenderPass present_load_renderpass;
|
||||
std::vector<Frame> swap_chain;
|
||||
std::queue<Frame*> free_queue;
|
||||
std::queue<Frame*> present_queue;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue