mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-06 02:33:44 -04:00
Merge ccc59f8417 into 4e4c7e687b
This commit is contained in:
commit
d0a50eeb14
72 changed files with 25528 additions and 256 deletions
|
|
@ -47,6 +47,9 @@ foreach(KEY IN ITEMS
|
|||
"frame_limit"
|
||||
"turbo_limit"
|
||||
"texture_filter"
|
||||
"antialiasing_filter"
|
||||
"output_scaling"
|
||||
"fsr_sharpness"
|
||||
"texture_sampling"
|
||||
"delay_game_render_thread_us"
|
||||
"simulate_3ds_gpu_timings"
|
||||
|
|
|
|||
|
|
@ -725,6 +725,9 @@ void QtConfig::ReadRendererValues() {
|
|||
ReadGlobalSetting(Settings::values.bg_blue);
|
||||
|
||||
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);
|
||||
|
|
@ -1274,6 +1277,9 @@ void QtConfig::SaveRendererValues() {
|
|||
WriteGlobalSetting(Settings::values.bg_blue);
|
||||
|
||||
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);
|
||||
|
|
@ -48,13 +56,25 @@ void ConfigureEnhancements::SetConfiguration() {
|
|||
&Settings::values.texture_filter);
|
||||
ConfigurationShared::SetHighlight(ui->widget_texture_filter,
|
||||
!Settings::values.texture_filter.UsingGlobal());
|
||||
ConfigurationShared::SetPerGameSetting(ui->antialiasing_filter_combobox,
|
||||
&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());
|
||||
ui->texture_filter_combobox->setCurrentIndex(
|
||||
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());
|
||||
|
|
@ -62,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());
|
||||
|
|
@ -71,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);
|
||||
|
|
@ -124,14 +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,
|
||||
|
|
@ -150,7 +179,8 @@ void ConfigureEnhancements::SetupPerGameUI() {
|
|||
if (Settings::IsConfiguringGlobal()) {
|
||||
ui->widget_resolution->setEnabled(Settings::values.resolution_factor.UsingGlobal());
|
||||
ui->widget_texture_filter->setEnabled(Settings::values.texture_filter.UsingGlobal());
|
||||
ui->toggle_linear_filter->setEnabled(Settings::values.filter_mode.UsingGlobal());
|
||||
ui->widget_antialiasing_filter->setEnabled(Settings::values.antialiasing_filter.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());
|
||||
|
|
@ -168,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,
|
||||
|
|
@ -192,4 +220,12 @@ void ConfigureEnhancements::SetupPerGameUI() {
|
|||
ConfigurationShared::SetColoredComboBox(
|
||||
ui->texture_filter_combobox, ui->widget_texture_filter,
|
||||
static_cast<int>(Settings::values.texture_filter.GetValue(true)));
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -112,19 +112,237 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="use_integer_scaling">
|
||||
<property name="text">
|
||||
<string>Use Integer Scaling</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use Integer Scaling</p><p>Enforces that the larger screen in all layouts is an integer scale of the 240px height of the original 3DS screen.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Integer Scaling</string>
|
||||
</property>
|
||||
</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>
|
||||
<widget class="QWidget" name="widget_antialiasing_filter" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<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="antialiasing_filter_label">
|
||||
<property name="text">
|
||||
<string>Anti-Aliasing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="antialiasing_filter_combobox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>FXAA</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>SMAA</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
|
@ -329,12 +547,12 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="disable_right_eye_render">
|
||||
<property name="text">
|
||||
<string>Disable Right Eye Rendering</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Disable Right Eye Rendering</p><p>Disables rendering the right eye image when not using stereoscopic mode. Greatly improves performance in some applications, but can cause flickering in others.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Disable Right Eye Rendering</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
|
@ -399,7 +617,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -413,9 +631,9 @@
|
|||
</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>
|
||||
<tabstop>render_3d_combobox</tabstop>
|
||||
<tabstop>factor_3d</tabstop>
|
||||
<tabstop>mono_rendering_eye</tabstop>
|
||||
|
|
|
|||
|
|
@ -57,6 +57,35 @@ std::string_view GetTextureFilterName(TextureFilter filter) {
|
|||
}
|
||||
}
|
||||
|
||||
std::string_view GetAntialiasingFilterName(AntiAliasingFilter filter) {
|
||||
switch (filter) {
|
||||
case AntiAliasingFilter::None:
|
||||
return "None";
|
||||
case AntiAliasingFilter::FXAA:
|
||||
return "FXAA";
|
||||
case AntiAliasingFilter::SMAA:
|
||||
return "SMAA";
|
||||
default:
|
||||
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:
|
||||
|
|
@ -103,6 +132,8 @@ void LogSettings() {
|
|||
log_setting("Renderer_PostProcessingShader", values.pp_shader_name.GetValue());
|
||||
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());
|
||||
|
|
@ -216,6 +247,9 @@ void RestoreGlobalState(bool is_powered_on) {
|
|||
values.use_integer_scaling.SetGlobal(true);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -112,6 +112,20 @@ enum class TextureFilter : u32 {
|
|||
MMPX = 5,
|
||||
};
|
||||
|
||||
enum class AntiAliasingFilter : u32 {
|
||||
None = 0,
|
||||
FXAA = 1,
|
||||
SMAA = 2,
|
||||
};
|
||||
|
||||
enum class OutputScaling : u32 {
|
||||
Nearest = 0,
|
||||
Bilinear = 1,
|
||||
Adaptive = 2,
|
||||
FSR = 3,
|
||||
SharpBilinear = 4,
|
||||
};
|
||||
|
||||
enum class TextureSampling : u32 {
|
||||
GameControlled = 0,
|
||||
NearestNeighbor = 1,
|
||||
|
|
@ -539,6 +553,9 @@ struct Values {
|
|||
SwitchableSetting<double, true> frame_limit{100, 0, 1000, Keys::frame_limit};
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -13,17 +13,66 @@ set(SHADER_FILES
|
|||
texture_filtering/mmpx.frag
|
||||
texture_filtering/x_gradient.frag
|
||||
texture_filtering/y_gradient.frag
|
||||
antialiasing/OpenGL/opengl_fxaa.frag
|
||||
antialiasing/OpenGL/opengl_fxaa.vert
|
||||
antialiasing/OpenGL/opengl_smaa_pass0_pre.frag
|
||||
antialiasing/OpenGL/opengl_smaa_pass0_pre.vert
|
||||
antialiasing/OpenGL/opengl_smaa_pass0_post.frag
|
||||
antialiasing/OpenGL/opengl_smaa_pass0_post.vert
|
||||
antialiasing/OpenGL/opengl_smaa_pass1_pre.frag
|
||||
antialiasing/OpenGL/opengl_smaa_pass1_pre.vert
|
||||
antialiasing/OpenGL/opengl_smaa_pass1_post.frag
|
||||
antialiasing/OpenGL/opengl_smaa_pass1_post.vert
|
||||
antialiasing/OpenGL/opengl_smaa_pass2_pre.frag
|
||||
antialiasing/OpenGL/opengl_smaa_pass2_pre.vert
|
||||
antialiasing/OpenGL/opengl_smaa_pass2_post.frag
|
||||
antialiasing/OpenGL/opengl_smaa_pass2_post.vert
|
||||
antialiasing/OpenGL/opengl_smaa.hlsl
|
||||
antialiasing/Vulkan/vulkan_fxaa.frag
|
||||
antialiasing/Vulkan/vulkan_fxaa.vert
|
||||
antialiasing/Vulkan/vulkan_smaa_pass0_pre.frag
|
||||
antialiasing/Vulkan/vulkan_smaa_pass0_pre.vert
|
||||
antialiasing/Vulkan/vulkan_smaa_pass0_post.frag
|
||||
antialiasing/Vulkan/vulkan_smaa_pass0_post.vert
|
||||
antialiasing/Vulkan/vulkan_smaa_pass1_pre.frag
|
||||
antialiasing/Vulkan/vulkan_smaa_pass1_pre.vert
|
||||
antialiasing/Vulkan/vulkan_smaa_pass1_post.frag
|
||||
antialiasing/Vulkan/vulkan_smaa_pass1_post.vert
|
||||
antialiasing/Vulkan/vulkan_smaa_pass2_pre.frag
|
||||
antialiasing/Vulkan/vulkan_smaa_pass2_pre.vert
|
||||
antialiasing/Vulkan/vulkan_smaa_pass2_post.frag
|
||||
antialiasing/Vulkan/vulkan_smaa_pass2_post.vert
|
||||
antialiasing/Vulkan/vulkan_smaa.hlsl
|
||||
scaling/opengl_area_sampling.frag
|
||||
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
|
||||
opengl_present_anaglyph.frag
|
||||
opengl_present_interlaced.frag
|
||||
opengl_simple_present.frag
|
||||
opengl_simple_present.vert
|
||||
vulkan_depth_to_buffer.comp
|
||||
vulkan_present.frag
|
||||
vulkan_present.vert
|
||||
vulkan_present_anaglyph.frag
|
||||
vulkan_present_interlaced.frag
|
||||
vulkan_blit_depth_stencil.frag
|
||||
vulkan_simple_present.frag
|
||||
vulkan_simple_present.vert
|
||||
vulkan_cursor.frag
|
||||
vulkan_cursor.vert
|
||||
)
|
||||
|
|
|
|||
14980
src/video_core/host_shaders/antialiasing/AreaTex.h
Normal file
14980
src/video_core/host_shaders/antialiasing/AreaTex.h
Normal file
File diff suppressed because it is too large
Load diff
256
src/video_core/host_shaders/antialiasing/OpenGL/opengl_fxaa.frag
Normal file
256
src/video_core/host_shaders/antialiasing/OpenGL/opengl_fxaa.frag
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright (c) 2011 NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
|
||||
* *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
|
||||
* OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT,IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA
|
||||
* OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS
|
||||
* OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY
|
||||
* OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
/*
|
||||
FXAA_PRESET - Choose compile-in knob preset 0-5.
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_EDGE_THRESHOLD - The minimum amount of local contrast required
|
||||
to apply algorithm.
|
||||
1.0/3.0 - too little
|
||||
1.0/4.0 - good start
|
||||
1.0/8.0 - applies to more edges
|
||||
1.0/16.0 - overkill
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_EDGE_THRESHOLD_MIN - Trims the algorithm from processing darks.
|
||||
Perf optimization.
|
||||
1.0/32.0 - visible limit (smaller isn't visible)
|
||||
1.0/16.0 - good compromise
|
||||
1.0/12.0 - upper limit (seeing artifacts)
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SEARCH_STEPS - Maximum number of search steps for end of span.
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SEARCH_THRESHOLD - Controls when to stop searching.
|
||||
1.0/4.0 - seems to be the best quality wise
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SUBPIX_TRIM - Controls sub-pixel aliasing removal.
|
||||
1.0/2.0 - low removal
|
||||
1.0/3.0 - medium removal
|
||||
1.0/4.0 - default removal
|
||||
1.0/8.0 - high removal
|
||||
0.0 - complete removal
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SUBPIX_CAP - Insures fine detail is not completely removed.
|
||||
This is important for the transition of sub-pixel detail,
|
||||
like fences and wires.
|
||||
3.0/4.0 - default (medium amount of filtering)
|
||||
7.0/8.0 - high amount of filtering
|
||||
1.0 - no capping of sub-pixel aliasing removal
|
||||
*/
|
||||
//? #version 450
|
||||
|
||||
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 int convert_colors;
|
||||
|
||||
#ifndef FXAA_PRESET
|
||||
#define FXAA_PRESET 5
|
||||
#endif
|
||||
#if (FXAA_PRESET == 3)
|
||||
#define FXAA_EDGE_THRESHOLD (1.0/8.0)
|
||||
#define FXAA_EDGE_THRESHOLD_MIN (1.0/16.0)
|
||||
#define FXAA_SEARCH_STEPS 16
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/4.0)
|
||||
#define FXAA_SUBPIX_CAP (3.0/4.0)
|
||||
#define FXAA_SUBPIX_TRIM (1.0/4.0)
|
||||
#endif
|
||||
#if (FXAA_PRESET == 4)
|
||||
#define FXAA_EDGE_THRESHOLD (1.0/8.0)
|
||||
#define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
|
||||
#define FXAA_SEARCH_STEPS 24
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/4.0)
|
||||
#define FXAA_SUBPIX_CAP (3.0/4.0)
|
||||
#define FXAA_SUBPIX_TRIM (1.0/4.0)
|
||||
#endif
|
||||
#if (FXAA_PRESET == 5)
|
||||
#define FXAA_EDGE_THRESHOLD (1.0/8.0)
|
||||
#define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
|
||||
#define FXAA_SEARCH_STEPS 32
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/4.0)
|
||||
#define FXAA_SUBPIX_CAP (3.0/4.0)
|
||||
#define FXAA_SUBPIX_TRIM (1.0/4.0)
|
||||
#endif
|
||||
|
||||
#define FXAA_SUBPIX_TRIM_SCALE (1.0/(1.0 - FXAA_SUBPIX_TRIM))
|
||||
|
||||
// Return the luma, the estimation of luminance from rgb inputs.
|
||||
// This approximates luma using one FMA instruction,
|
||||
// skipping normalization and tossing out blue.
|
||||
// FxaaLuma() will range 0.0 to 2.963210702.
|
||||
float FxaaLuma(vec3 rgb) {
|
||||
return rgb.y * (0.587/0.299) + rgb.x;
|
||||
}
|
||||
|
||||
vec3 FxaaLerp3(vec3 a, vec3 b, float amountOfA) {
|
||||
return (vec3(-amountOfA) * b) + ((a * vec3(amountOfA)) + b);
|
||||
}
|
||||
|
||||
vec4 FxaaTexOff(sampler2D tex, vec2 pos, ivec2 off, vec2 rcpFrame) {
|
||||
float x = pos.x + float(off.x) * rcpFrame.x;
|
||||
float y = pos.y + float(off.y) * rcpFrame.y;
|
||||
return texture(tex, vec2(x, y));
|
||||
}
|
||||
|
||||
// pos is the output of FxaaVertexShader interpolated across screen.
|
||||
// xy -> actual texture position {0.0 to 1.0}
|
||||
// rcpFrame should be a uniform equal to {1.0/frameWidth, 1.0/frameHeight}
|
||||
vec3 FxaaPixelShader(vec2 pos, sampler2D tex, vec2 rcpFrame)
|
||||
{
|
||||
vec3 rgbN = FxaaTexOff(tex, pos.xy, ivec2( 0,-1), rcpFrame).xyz;
|
||||
vec3 rgbW = FxaaTexOff(tex, pos.xy, ivec2(-1, 0), rcpFrame).xyz;
|
||||
vec3 rgbM = FxaaTexOff(tex, pos.xy, ivec2( 0, 0), rcpFrame).xyz;
|
||||
vec3 rgbE = FxaaTexOff(tex, pos.xy, ivec2( 1, 0), rcpFrame).xyz;
|
||||
vec3 rgbS = FxaaTexOff(tex, pos.xy, ivec2( 0, 1), rcpFrame).xyz;
|
||||
|
||||
float lumaN = FxaaLuma(rgbN);
|
||||
float lumaW = FxaaLuma(rgbW);
|
||||
float lumaM = FxaaLuma(rgbM);
|
||||
float lumaE = FxaaLuma(rgbE);
|
||||
float lumaS = FxaaLuma(rgbS);
|
||||
float rangeMin = min(lumaM, min(min(lumaN, lumaW), min(lumaS, lumaE)));
|
||||
float rangeMax = max(lumaM, max(max(lumaN, lumaW), max(lumaS, lumaE)));
|
||||
|
||||
float range = rangeMax - rangeMin;
|
||||
if(range < max(FXAA_EDGE_THRESHOLD_MIN, rangeMax * FXAA_EDGE_THRESHOLD))
|
||||
{
|
||||
return rgbM;
|
||||
}
|
||||
|
||||
vec3 rgbL = rgbN + rgbW + rgbM + rgbE + rgbS;
|
||||
|
||||
float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25;
|
||||
float rangeL = abs(lumaL - lumaM);
|
||||
float blendL = max(0.0, (rangeL / range) - FXAA_SUBPIX_TRIM) * FXAA_SUBPIX_TRIM_SCALE;
|
||||
blendL = min(FXAA_SUBPIX_CAP, blendL);
|
||||
|
||||
vec3 rgbNW = FxaaTexOff(tex, pos.xy, ivec2(-1,-1), rcpFrame).xyz;
|
||||
vec3 rgbNE = FxaaTexOff(tex, pos.xy, ivec2( 1,-1), rcpFrame).xyz;
|
||||
vec3 rgbSW = FxaaTexOff(tex, pos.xy, ivec2(-1, 1), rcpFrame).xyz;
|
||||
vec3 rgbSE = FxaaTexOff(tex, pos.xy, ivec2( 1, 1), rcpFrame).xyz;
|
||||
rgbL += (rgbNW + rgbNE + rgbSW + rgbSE);
|
||||
rgbL *= vec3(1.0/9.0);
|
||||
|
||||
float lumaNW = FxaaLuma(rgbNW);
|
||||
float lumaNE = FxaaLuma(rgbNE);
|
||||
float lumaSW = FxaaLuma(rgbSW);
|
||||
float lumaSE = FxaaLuma(rgbSE);
|
||||
|
||||
float edgeVert =
|
||||
abs((0.25 * lumaNW) + (-0.5 * lumaN) + (0.25 * lumaNE)) +
|
||||
abs((0.50 * lumaW ) + (-1.0 * lumaM) + (0.50 * lumaE )) +
|
||||
abs((0.25 * lumaSW) + (-0.5 * lumaS) + (0.25 * lumaSE));
|
||||
float edgeHorz =
|
||||
abs((0.25 * lumaNW) + (-0.5 * lumaW) + (0.25 * lumaSW)) +
|
||||
abs((0.50 * lumaN ) + (-1.0 * lumaM) + (0.50 * lumaS )) +
|
||||
abs((0.25 * lumaNE) + (-0.5 * lumaE) + (0.25 * lumaSE));
|
||||
|
||||
bool horzSpan = edgeHorz >= edgeVert;
|
||||
float lengthSign = horzSpan ? -rcpFrame.y : -rcpFrame.x;
|
||||
|
||||
if(!horzSpan)
|
||||
{
|
||||
lumaN = lumaW;
|
||||
lumaS = lumaE;
|
||||
}
|
||||
|
||||
float gradientN = abs(lumaN - lumaM);
|
||||
float gradientS = abs(lumaS - lumaM);
|
||||
lumaN = (lumaN + lumaM) * 0.5;
|
||||
lumaS = (lumaS + lumaM) * 0.5;
|
||||
|
||||
if (gradientN < gradientS)
|
||||
{
|
||||
lumaN = lumaS;
|
||||
lumaN = lumaS;
|
||||
gradientN = gradientS;
|
||||
lengthSign *= -1.0;
|
||||
}
|
||||
|
||||
vec2 posN;
|
||||
posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5);
|
||||
posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0);
|
||||
|
||||
gradientN *= FXAA_SEARCH_THRESHOLD;
|
||||
|
||||
vec2 posP = posN;
|
||||
vec2 offNP = horzSpan ? vec2(rcpFrame.x, 0.0) : vec2(0.0, rcpFrame.y);
|
||||
float lumaEndN = lumaN;
|
||||
float lumaEndP = lumaN;
|
||||
bool doneN = false;
|
||||
bool doneP = false;
|
||||
posN += offNP * vec2(-1.0, -1.0);
|
||||
posP += offNP * vec2( 1.0, 1.0);
|
||||
|
||||
for(int i = 0; i < FXAA_SEARCH_STEPS; i++) {
|
||||
if(!doneN)
|
||||
{
|
||||
lumaEndN = FxaaLuma(texture(tex, posN.xy).xyz);
|
||||
}
|
||||
if(!doneP)
|
||||
{
|
||||
lumaEndP = FxaaLuma(texture(tex, posP.xy).xyz);
|
||||
}
|
||||
|
||||
doneN = doneN || (abs(lumaEndN - lumaN) >= gradientN);
|
||||
doneP = doneP || (abs(lumaEndP - lumaN) >= gradientN);
|
||||
|
||||
if(doneN && doneP)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(!doneN)
|
||||
{
|
||||
posN -= offNP;
|
||||
}
|
||||
if(!doneP)
|
||||
{
|
||||
posP += offNP;
|
||||
}
|
||||
}
|
||||
|
||||
float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y;
|
||||
float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y;
|
||||
bool directionN = dstN < dstP;
|
||||
lumaEndN = directionN ? lumaEndN : lumaEndP;
|
||||
|
||||
if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0))
|
||||
{
|
||||
lengthSign = 0.0;
|
||||
}
|
||||
|
||||
|
||||
float spanLength = (dstP + dstN);
|
||||
dstN = directionN ? dstN : dstP;
|
||||
float subPixelOffset = (0.5 + (dstN * (-1.0/spanLength))) * lengthSign;
|
||||
vec3 rgbF = texture(tex, vec2(
|
||||
pos.x + (horzSpan ? 0.0 : subPixelOffset),
|
||||
pos.y + (horzSpan ? subPixelOffset : 0.0))).xyz;
|
||||
return FxaaLerp3(rgbL, rgbF, blendL);
|
||||
}
|
||||
|
||||
vec3 sRGBToLinear(vec3 c) {
|
||||
return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(0.04045, c));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
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);
|
||||
}
|
||||
color = pixel;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
//? #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;
|
||||
|
||||
uniform vec4 i_resolution;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
}
|
||||
|
||||
1459
src/video_core/host_shaders/antialiasing/OpenGL/opengl_smaa.hlsl
Normal file
1459
src/video_core/host_shaders/antialiasing/OpenGL/opengl_smaa.hlsl
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,7 @@
|
|||
void main() {
|
||||
if (SMAA_EDT == 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, color_texture), 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
void main() {
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
SMAAEdgeDetectionVS(vert_tex_coord, offset);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//? #version 450
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Edge Detection Shaders (First Pass)
|
||||
|
||||
uniform vec4 i_resolution;
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 1
|
||||
#define SMAA_FLIP_Y 1
|
||||
#define SMAA_FLIP_Y 1
|
||||
#define SMAA_FLIP_Y 1
|
||||
#define SMAA_FLIP_Y 1
|
||||
#define SMAA_FLIP_Y 1
|
||||
#define SMAA_FLIP_Y 1
|
||||
#define SMAA_PRESET_ULTRA
|
||||
#define SMAA_EDT 1.0
|
||||
|
||||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 1) in vec4 offset[3];
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
#define SMAA_INCLUDE_VS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
//? #version 450
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Edge Detection Shaders (First Pass)
|
||||
|
||||
uniform vec4 i_resolution;
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 1
|
||||
#define SMAA_PRESET_ULTRA
|
||||
#define SMAA_EDT 1.0
|
||||
|
||||
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 vec4 offset[3];
|
||||
|
||||
#define SMAA_INCLUDE_PS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
void main() {
|
||||
vec4 subsampleIndices = vec4(0.0);
|
||||
color = SMAABlendingWeightCalculationPS(frag_tex_coord, pixcoord, offset, color_texture, areaTex, searchTex, subsampleIndices);
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
void main() {
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
SMAABlendingWeightCalculationVS(vert_tex_coord, pixcoord, offset);
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
//? #version 450
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Blending Weight Calculation Shader (Second Pass)
|
||||
|
||||
uniform vec4 i_resolution;
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 1
|
||||
#define SMAA_PRESET_ULTRA
|
||||
#define SMAA_EDT 1.0
|
||||
|
||||
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(binding = 0) uniform sampler2D color_texture;
|
||||
uniform sampler2D areaTex;
|
||||
uniform sampler2D searchTex;
|
||||
|
||||
#define SMAA_INCLUDE_VS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
//? #version 450
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Blending Weight Calculation Shader (Second Pass)
|
||||
|
||||
uniform vec4 i_resolution;
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 1
|
||||
#define SMAA_PRESET_ULTRA
|
||||
#define SMAA_EDT 1.0
|
||||
|
||||
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 pixcoord;
|
||||
layout(location = 2) out vec4 offset[3];
|
||||
|
||||
#define SMAA_INCLUDE_PS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
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() {
|
||||
vec4 pixel = SMAANeighborhoodBlendingPS(frag_tex_coord, offset, SMAA_Input, color_texture);
|
||||
if (convert_colors == 2){
|
||||
pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a);
|
||||
}
|
||||
color = pixel;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
void main() {
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
SMAANeighborhoodBlendingVS(vert_tex_coord, offset);
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
//? #version 450
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Neighborhood Blending Shader (Third Pass)
|
||||
|
||||
uniform vec4 i_resolution;
|
||||
uniform int convert_colors;
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 1
|
||||
|
||||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 1) in vec4 offset;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(binding = 0) uniform sampler2D color_texture;
|
||||
uniform sampler2D SMAA_Input;
|
||||
|
||||
#define SMAA_INCLUDE_VS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
//? #version 450
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Neighborhood Blending Shader (Third Pass)
|
||||
|
||||
uniform vec4 i_resolution;
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 1
|
||||
|
||||
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 vec4 offset;
|
||||
|
||||
#define SMAA_INCLUDE_PS 0
|
||||
//#include "SMAA.hlsl"
|
||||
132
src/video_core/host_shaders/antialiasing/SearchTex.h
Normal file
132
src/video_core/host_shaders/antialiasing/SearchTex.h
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/**
|
||||
* Copyright (C) 2013 Jorge Jimenez (jorge@iryoku.com)
|
||||
* Copyright (C) 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com)
|
||||
* Copyright (C) 2013 Belen Masia (bmasia@unizar.es)
|
||||
* Copyright (C) 2013 Fernando Navarro (fernandn@microsoft.com)
|
||||
* Copyright (C) 2013 Diego Gutierrez (diegog@unizar.es)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to
|
||||
* do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software. As clarification, there
|
||||
* is no requirement that the copyright notice and permission be included in
|
||||
* binary distributions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SEARCHTEX_H
|
||||
#define SEARCHTEX_H
|
||||
|
||||
#define SEARCHTEX_WIDTH 64
|
||||
#define SEARCHTEX_HEIGHT 16
|
||||
#define SEARCHTEX_PITCH SEARCHTEX_WIDTH
|
||||
#define SEARCHTEX_SIZE (SEARCHTEX_HEIGHT * SEARCHTEX_PITCH)
|
||||
|
||||
/**
|
||||
* Stored in R8 format. Load it in the following format:
|
||||
* - DX9: D3DFMT_L8
|
||||
* - DX10: DXGI_FORMAT_R8_UNORM
|
||||
*/
|
||||
static const unsigned char searchTexBytes[] = {
|
||||
0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0xfe, 0x7f, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe,
|
||||
0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0xfe, 0x7f, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe,
|
||||
0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f,
|
||||
0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f,
|
||||
0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f,
|
||||
0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
#endif
|
||||
265
src/video_core/host_shaders/antialiasing/Vulkan/vulkan_fxaa.frag
Normal file
265
src/video_core/host_shaders/antialiasing/Vulkan/vulkan_fxaa.frag
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright (c) 2011 NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
|
||||
* *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
|
||||
* OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT,IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA
|
||||
* OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS
|
||||
* OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY
|
||||
* OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
|
||||
* EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
/*
|
||||
FXAA_PRESET - Choose compile-in knob preset 0-5.
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_EDGE_THRESHOLD - The minimum amount of local contrast required
|
||||
to apply algorithm.
|
||||
1.0/3.0 - too little
|
||||
1.0/4.0 - good start
|
||||
1.0/8.0 - applies to more edges
|
||||
1.0/16.0 - overkill
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_EDGE_THRESHOLD_MIN - Trims the algorithm from processing darks.
|
||||
Perf optimization.
|
||||
1.0/32.0 - visible limit (smaller isn't visible)
|
||||
1.0/16.0 - good compromise
|
||||
1.0/12.0 - upper limit (seeing artifacts)
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SEARCH_STEPS - Maximum number of search steps for end of span.
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SEARCH_THRESHOLD - Controls when to stop searching.
|
||||
1.0/4.0 - seems to be the best quality wise
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SUBPIX_TRIM - Controls sub-pixel aliasing removal.
|
||||
1.0/2.0 - low removal
|
||||
1.0/3.0 - medium removal
|
||||
1.0/4.0 - default removal
|
||||
1.0/8.0 - high removal
|
||||
0.0 - complete removal
|
||||
------------------------------------------------------------------------------
|
||||
FXAA_SUBPIX_CAP - Insures fine detail is not completely removed.
|
||||
This is important for the transition of sub-pixel detail,
|
||||
like fences and wires.
|
||||
3.0/4.0 - default (medium amount of filtering)
|
||||
7.0/8.0 - high amount of filtering
|
||||
1.0 - no capping of sub-pixel aliasing removal
|
||||
*/
|
||||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
#ifndef FXAA_PRESET
|
||||
#define FXAA_PRESET 5
|
||||
#endif
|
||||
#if (FXAA_PRESET == 3)
|
||||
#define FXAA_EDGE_THRESHOLD (1.0/8.0)
|
||||
#define FXAA_EDGE_THRESHOLD_MIN (1.0/16.0)
|
||||
#define FXAA_SEARCH_STEPS 16
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/4.0)
|
||||
#define FXAA_SUBPIX_CAP (3.0/4.0)
|
||||
#define FXAA_SUBPIX_TRIM (1.0/4.0)
|
||||
#endif
|
||||
#if (FXAA_PRESET == 4)
|
||||
#define FXAA_EDGE_THRESHOLD (1.0/8.0)
|
||||
#define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
|
||||
#define FXAA_SEARCH_STEPS 24
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/4.0)
|
||||
#define FXAA_SUBPIX_CAP (3.0/4.0)
|
||||
#define FXAA_SUBPIX_TRIM (1.0/4.0)
|
||||
#endif
|
||||
#if (FXAA_PRESET == 5)
|
||||
#define FXAA_EDGE_THRESHOLD (1.0/8.0)
|
||||
#define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0)
|
||||
#define FXAA_SEARCH_STEPS 32
|
||||
#define FXAA_SEARCH_THRESHOLD (1.0/4.0)
|
||||
#define FXAA_SUBPIX_CAP (3.0/4.0)
|
||||
#define FXAA_SUBPIX_TRIM (1.0/4.0)
|
||||
#endif
|
||||
|
||||
#define FXAA_SUBPIX_TRIM_SCALE (1.0/(1.0 - FXAA_SUBPIX_TRIM))
|
||||
|
||||
// Return the luma, the estimation of luminance from rgb inputs.
|
||||
// This approximates luma using one FMA instruction,
|
||||
// skipping normalization and tossing out blue.
|
||||
// FxaaLuma() will range 0.0 to 2.963210702.
|
||||
float FxaaLuma(vec3 rgb) {
|
||||
return rgb.y * (0.587/0.299) + rgb.x;
|
||||
}
|
||||
|
||||
vec3 FxaaLerp3(vec3 a, vec3 b, float amountOfA) {
|
||||
return (vec3(-amountOfA) * b) + ((a * vec3(amountOfA)) + b);
|
||||
}
|
||||
|
||||
vec4 FxaaTexOff(sampler2D tex, vec2 pos, ivec2 off, vec2 rcpFrame) {
|
||||
float x = pos.x + float(off.x) * rcpFrame.x;
|
||||
float y = pos.y + float(off.y) * rcpFrame.y;
|
||||
return texture(tex, vec2(x, y));
|
||||
}
|
||||
|
||||
// pos is the output of FxaaVertexShader interpolated across screen.
|
||||
// xy -> actual texture position {0.0 to 1.0}
|
||||
// rcpFrame should be a uniform equal to {1.0/frameWidth, 1.0/frameHeight}
|
||||
vec3 FxaaPixelShader(vec2 pos, sampler2D tex, vec2 rcpFrame)
|
||||
{
|
||||
vec3 rgbN = FxaaTexOff(tex, pos.xy, ivec2( 0,-1), rcpFrame).xyz;
|
||||
vec3 rgbW = FxaaTexOff(tex, pos.xy, ivec2(-1, 0), rcpFrame).xyz;
|
||||
vec3 rgbM = FxaaTexOff(tex, pos.xy, ivec2( 0, 0), rcpFrame).xyz;
|
||||
vec3 rgbE = FxaaTexOff(tex, pos.xy, ivec2( 1, 0), rcpFrame).xyz;
|
||||
vec3 rgbS = FxaaTexOff(tex, pos.xy, ivec2( 0, 1), rcpFrame).xyz;
|
||||
|
||||
float lumaN = FxaaLuma(rgbN);
|
||||
float lumaW = FxaaLuma(rgbW);
|
||||
float lumaM = FxaaLuma(rgbM);
|
||||
float lumaE = FxaaLuma(rgbE);
|
||||
float lumaS = FxaaLuma(rgbS);
|
||||
float rangeMin = min(lumaM, min(min(lumaN, lumaW), min(lumaS, lumaE)));
|
||||
float rangeMax = max(lumaM, max(max(lumaN, lumaW), max(lumaS, lumaE)));
|
||||
|
||||
float range = rangeMax - rangeMin;
|
||||
if(range < max(FXAA_EDGE_THRESHOLD_MIN, rangeMax * FXAA_EDGE_THRESHOLD))
|
||||
{
|
||||
return rgbM;
|
||||
}
|
||||
|
||||
vec3 rgbL = rgbN + rgbW + rgbM + rgbE + rgbS;
|
||||
|
||||
float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25;
|
||||
float rangeL = abs(lumaL - lumaM);
|
||||
float blendL = max(0.0, (rangeL / range) - FXAA_SUBPIX_TRIM) * FXAA_SUBPIX_TRIM_SCALE;
|
||||
blendL = min(FXAA_SUBPIX_CAP, blendL);
|
||||
|
||||
vec3 rgbNW = FxaaTexOff(tex, pos.xy, ivec2(-1,-1), rcpFrame).xyz;
|
||||
vec3 rgbNE = FxaaTexOff(tex, pos.xy, ivec2( 1,-1), rcpFrame).xyz;
|
||||
vec3 rgbSW = FxaaTexOff(tex, pos.xy, ivec2(-1, 1), rcpFrame).xyz;
|
||||
vec3 rgbSE = FxaaTexOff(tex, pos.xy, ivec2( 1, 1), rcpFrame).xyz;
|
||||
rgbL += (rgbNW + rgbNE + rgbSW + rgbSE);
|
||||
rgbL *= vec3(1.0/9.0);
|
||||
|
||||
float lumaNW = FxaaLuma(rgbNW);
|
||||
float lumaNE = FxaaLuma(rgbNE);
|
||||
float lumaSW = FxaaLuma(rgbSW);
|
||||
float lumaSE = FxaaLuma(rgbSE);
|
||||
|
||||
float edgeVert =
|
||||
abs((0.25 * lumaNW) + (-0.5 * lumaN) + (0.25 * lumaNE)) +
|
||||
abs((0.50 * lumaW ) + (-1.0 * lumaM) + (0.50 * lumaE )) +
|
||||
abs((0.25 * lumaSW) + (-0.5 * lumaS) + (0.25 * lumaSE));
|
||||
float edgeHorz =
|
||||
abs((0.25 * lumaNW) + (-0.5 * lumaW) + (0.25 * lumaSW)) +
|
||||
abs((0.50 * lumaN ) + (-1.0 * lumaM) + (0.50 * lumaS )) +
|
||||
abs((0.25 * lumaNE) + (-0.5 * lumaE) + (0.25 * lumaSE));
|
||||
|
||||
bool horzSpan = edgeHorz >= edgeVert;
|
||||
float lengthSign = horzSpan ? -rcpFrame.y : -rcpFrame.x;
|
||||
|
||||
if(!horzSpan)
|
||||
{
|
||||
lumaN = lumaW;
|
||||
lumaS = lumaE;
|
||||
}
|
||||
|
||||
float gradientN = abs(lumaN - lumaM);
|
||||
float gradientS = abs(lumaS - lumaM);
|
||||
lumaN = (lumaN + lumaM) * 0.5;
|
||||
lumaS = (lumaS + lumaM) * 0.5;
|
||||
|
||||
if (gradientN < gradientS)
|
||||
{
|
||||
lumaN = lumaS;
|
||||
lumaN = lumaS;
|
||||
gradientN = gradientS;
|
||||
lengthSign *= -1.0;
|
||||
}
|
||||
|
||||
vec2 posN;
|
||||
posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5);
|
||||
posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0);
|
||||
|
||||
gradientN *= FXAA_SEARCH_THRESHOLD;
|
||||
|
||||
vec2 posP = posN;
|
||||
vec2 offNP = horzSpan ? vec2(rcpFrame.x, 0.0) : vec2(0.0, rcpFrame.y);
|
||||
float lumaEndN = lumaN;
|
||||
float lumaEndP = lumaN;
|
||||
bool doneN = false;
|
||||
bool doneP = false;
|
||||
posN += offNP * vec2(-1.0, -1.0);
|
||||
posP += offNP * vec2( 1.0, 1.0);
|
||||
|
||||
for(int i = 0; i < FXAA_SEARCH_STEPS; i++) {
|
||||
if(!doneN)
|
||||
{
|
||||
lumaEndN = FxaaLuma(texture(tex, posN.xy).xyz);
|
||||
}
|
||||
if(!doneP)
|
||||
{
|
||||
lumaEndP = FxaaLuma(texture(tex, posP.xy).xyz);
|
||||
}
|
||||
|
||||
doneN = doneN || (abs(lumaEndN - lumaN) >= gradientN);
|
||||
doneP = doneP || (abs(lumaEndP - lumaN) >= gradientN);
|
||||
|
||||
if(doneN && doneP)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(!doneN)
|
||||
{
|
||||
posN -= offNP;
|
||||
}
|
||||
if(!doneP)
|
||||
{
|
||||
posP += offNP;
|
||||
}
|
||||
}
|
||||
|
||||
float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y;
|
||||
float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y;
|
||||
bool directionN = dstN < dstP;
|
||||
lumaEndN = directionN ? lumaEndN : lumaEndP;
|
||||
|
||||
if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0))
|
||||
{
|
||||
lengthSign = 0.0;
|
||||
}
|
||||
|
||||
|
||||
float spanLength = (dstP + dstN);
|
||||
dstN = directionN ? dstN : dstP;
|
||||
float subPixelOffset = (0.5 + (dstN * (-1.0/spanLength))) * lengthSign;
|
||||
vec3 rgbF = texture(tex, vec2(
|
||||
pos.x + (horzSpan ? 0.0 : subPixelOffset),
|
||||
pos.y + (horzSpan ? subPixelOffset : 0.0))).xyz;
|
||||
return FxaaLerp3(rgbL, rgbF, blendL);
|
||||
}
|
||||
|
||||
vec3 sRGBToLinear(vec3 c) {
|
||||
return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(0.04045, c));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
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);
|
||||
}
|
||||
color = pixel;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
1459
src/video_core/host_shaders/antialiasing/Vulkan/vulkan_smaa.hlsl
Normal file
1459
src/video_core/host_shaders/antialiasing/Vulkan/vulkan_smaa.hlsl
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,7 @@
|
|||
void main() {
|
||||
if (SMAA_EDT == 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, color_texture), 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
void main() {
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
SMAAEdgeDetectionVS(vert_tex_coord, offset);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Edge Detection Shaders (First Pass)
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 0
|
||||
#define SMAA_PRESET_ULTRA
|
||||
#define SMAA_EDT 1.0
|
||||
|
||||
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 color_texture;
|
||||
|
||||
#define SMAA_INCLUDE_VS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Edge Detection Shaders (First Pass)
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 0
|
||||
#define SMAA_PRESET_ULTRA
|
||||
#define SMAA_EDT 1.0
|
||||
|
||||
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 vec4 offset[3];
|
||||
|
||||
#define SMAA_INCLUDE_PS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
void main() {
|
||||
vec4 subsampleIndices = vec4(0.0);
|
||||
color = SMAABlendingWeightCalculationPS(frag_tex_coord, pixcoord, offset, color_texture, areaTex, searchTex, subsampleIndices);
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
void main() {
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
SMAABlendingWeightCalculationVS(vert_tex_coord, pixcoord, offset);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Blending Weight Calculation Shader (Second Pass)
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 0
|
||||
#define SMAA_PRESET_ULTRA
|
||||
#define SMAA_EDT 1.0
|
||||
|
||||
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 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"
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Blending Weight Calculation Shader (Second Pass)
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 0
|
||||
#define SMAA_PRESET_ULTRA
|
||||
#define SMAA_EDT 1.0
|
||||
|
||||
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 pixcoord;
|
||||
layout(location = 2) out vec4 offset[3];
|
||||
|
||||
#define SMAA_INCLUDE_PS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
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() {
|
||||
vec4 pixel = SMAANeighborhoodBlendingPS(frag_tex_coord, offset, SMAA_Input, color_texture);
|
||||
if (convert_colors == 2){
|
||||
pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a);
|
||||
}
|
||||
color = pixel;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
void main() {
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
SMAANeighborhoodBlendingVS(vert_tex_coord, offset);
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Neighborhood Blending Shader (Third Pass)
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 0
|
||||
|
||||
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 color_texture;
|
||||
layout (set = 0, binding = 1) uniform sampler2D SMAA_Input;
|
||||
|
||||
#define SMAA_INCLUDE_VS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
//-----------------------------------------------------------------------------
|
||||
// Neighborhood Blending Shader (Third Pass)
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
#define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y)
|
||||
#define SMAA_GLSL_4
|
||||
#define SMAA_FLIP_Y 0
|
||||
|
||||
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 vec4 offset;
|
||||
|
||||
#define SMAA_INCLUDE_PS 0
|
||||
//#include "SMAA.hlsl"
|
||||
|
|
@ -9,10 +9,22 @@ layout(location = 0) out vec4 color;
|
|||
|
||||
layout(binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
uniform vec4 i_resolution;
|
||||
uniform vec4 o_resolution;
|
||||
uniform int layer;
|
||||
uniform int convert_colors;
|
||||
|
||||
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 = texture(color_texture, frag_tex_coord);
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
28
src/video_core/host_shaders/opengl_simple_present.frag
Normal file
28
src/video_core/host_shaders/opengl_simple_present.frag
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
//? #version 430 core
|
||||
|
||||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout(binding = 0) uniform sampler2D color_texture;
|
||||
uniform int convert_colors;
|
||||
|
||||
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() {
|
||||
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;
|
||||
}
|
||||
13
src/video_core/host_shaders/opengl_simple_present.vert
Normal file
13
src/video_core/host_shaders/opengl_simple_present.vert
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
//? #version 430 core
|
||||
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,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;
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
//? #version 460 core
|
||||
|
||||
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;
|
||||
uniform int convert_colors;
|
||||
|
||||
|
||||
/***** Area Sampling *****/
|
||||
|
||||
// By Sam Belliveau and Filippo Tarpini. Public Domain license.
|
||||
// Effectively a more accurate sharp bilinear filter when upscaling,
|
||||
// that also works as a mathematically perfect downscale filter.
|
||||
// https://entropymine.com/imageworsener/pixelmixing/
|
||||
// https://github.com/obsproject/obs-studio/pull/1715
|
||||
// https://legacy.imagemagick.org/Usage/filter/
|
||||
vec4 AreaSampling(sampler2D textureSampler, vec2 texCoords) {
|
||||
// Determine the sizes of the source and target images.
|
||||
vec2 source_size = i_resolution.xy;
|
||||
vec2 inverted_target_size = o_resolution.zw;
|
||||
|
||||
// Determine the range of the source image that the target pixel will cover.
|
||||
vec2 range = source_size * inverted_target_size;
|
||||
vec2 beg = (texCoords.xy * source_size) - (range * 0.5);
|
||||
vec2 end = beg + range;
|
||||
|
||||
// Compute the top-left and bottom-right corners of the pixel box.
|
||||
ivec2 f_beg = ivec2(floor(beg));
|
||||
ivec2 f_end = ivec2(floor(end));
|
||||
|
||||
// Compute how much of the start and end pixels are covered horizontally & vertically.
|
||||
float area_w = 1.0 - fract(beg.x);
|
||||
float area_n = 1.0 - fract(beg.y);
|
||||
float area_e = fract(end.x);
|
||||
float area_s = fract(end.y);
|
||||
|
||||
// Compute the areas of the corner pixels in the pixel box.
|
||||
float area_nw = area_n * area_w;
|
||||
float area_ne = area_n * area_e;
|
||||
float area_sw = area_s * area_w;
|
||||
float area_se = area_s * area_e;
|
||||
|
||||
// Initialize the color accumulator.
|
||||
vec4 avg_color = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
// Accumulate corner pixels.
|
||||
avg_color += area_nw * texelFetch(textureSampler, ivec2(f_beg.x, f_beg.y), 0);
|
||||
avg_color += area_ne * texelFetch(textureSampler, ivec2(f_end.x, f_beg.y), 0);
|
||||
avg_color += area_sw * texelFetch(textureSampler, ivec2(f_beg.x, f_end.y), 0);
|
||||
avg_color += area_se * texelFetch(textureSampler, ivec2(f_end.x, f_end.y), 0);
|
||||
|
||||
// Determine the size of the pixel box.
|
||||
int x_range = int(f_end.x - f_beg.x - 0.5);
|
||||
int y_range = int(f_end.y - f_beg.y - 0.5);
|
||||
|
||||
// Accumulate top and bottom edge pixels.
|
||||
for (int x = f_beg.x + 1; x <= f_beg.x + x_range; ++x) {
|
||||
avg_color += area_n * texelFetch(textureSampler, ivec2(x, f_beg.y), 0);
|
||||
avg_color += area_s * texelFetch(textureSampler, ivec2(x, f_end.y), 0);
|
||||
}
|
||||
|
||||
// Accumulate left and right edge pixels and all the pixels in between.
|
||||
for (int y = f_beg.y + 1; y <= f_beg.y + y_range; ++y) {
|
||||
avg_color += area_w * texelFetch(textureSampler, ivec2(f_beg.x, y), 0);
|
||||
avg_color += area_e * texelFetch(textureSampler, ivec2(f_end.x, y), 0);
|
||||
|
||||
for (int x = f_beg.x + 1; x <= f_beg.x + x_range; ++x) {
|
||||
avg_color += texelFetch(textureSampler, ivec2(x, y), 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the area of the pixel box that was sampled.
|
||||
float area_corners = area_nw + area_ne + area_sw + area_se;
|
||||
float area_edges = float(x_range) * (area_n + area_s) + float(y_range) * (area_w + area_e);
|
||||
float area_center = float(x_range) * float(y_range);
|
||||
|
||||
// Return the normalized average color.
|
||||
return avg_color / (area_corners + area_edges + area_center);
|
||||
}
|
||||
|
||||
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() {
|
||||
vec4 pixel = AreaSampling(color_texture, frag_tex_coord);
|
||||
if (convert_colors == 2){
|
||||
pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a);
|
||||
}
|
||||
color = pixel;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
//? #version 460
|
||||
layout(location = 0) in vec2 vert_position;
|
||||
layout(location = 1) in vec2 vert_tex_coord;
|
||||
layout(location = 0) out vec2 frag_tex_coord;
|
||||
uniform mat3x2 modelview_matrix;
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
}
|
||||
|
||||
100
src/video_core/host_shaders/scaling/vulkan_area_sampling.frag
Normal file
100
src/video_core/host_shaders/scaling/vulkan_area_sampling.frag
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
//? #version 460 core
|
||||
|
||||
layout(location = 0) in vec2 frag_tex_coord;
|
||||
layout(location = 0) out vec4 color;
|
||||
layout (set = 0, binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
/***** Area Sampling *****/
|
||||
|
||||
// By Sam Belliveau and Filippo Tarpini. Public Domain license.
|
||||
// Effectively a more accurate sharp bilinear filter when upscaling,
|
||||
// that also works as a mathematically perfect downscale filter.
|
||||
// https://entropymine.com/imageworsener/pixelmixing/
|
||||
// https://github.com/obsproject/obs-studio/pull/1715
|
||||
// https://legacy.imagemagick.org/Usage/filter/
|
||||
vec4 AreaSampling(sampler2D textureSampler, vec2 texCoords) {
|
||||
// Determine the sizes of the source and target images.
|
||||
vec2 source_size = i_resolution.xy;
|
||||
vec2 inverted_target_size = o_resolution.zw;
|
||||
|
||||
// Determine the range of the source image that the target pixel will cover.
|
||||
vec2 range = source_size * inverted_target_size;
|
||||
vec2 beg = (texCoords.xy * source_size) - (range * 0.5);
|
||||
vec2 end = beg + range;
|
||||
|
||||
// Compute the top-left and bottom-right corners of the pixel box.
|
||||
ivec2 f_beg = ivec2(floor(beg));
|
||||
ivec2 f_end = ivec2(floor(end));
|
||||
|
||||
// Compute how much of the start and end pixels are covered horizontally & vertically.
|
||||
float area_w = 1.0 - fract(beg.x);
|
||||
float area_n = 1.0 - fract(beg.y);
|
||||
float area_e = fract(end.x);
|
||||
float area_s = fract(end.y);
|
||||
|
||||
// Compute the areas of the corner pixels in the pixel box.
|
||||
float area_nw = area_n * area_w;
|
||||
float area_ne = area_n * area_e;
|
||||
float area_sw = area_s * area_w;
|
||||
float area_se = area_s * area_e;
|
||||
|
||||
// Initialize the color accumulator.
|
||||
vec4 avg_color = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
// Accumulate corner pixels.
|
||||
avg_color += area_nw * texelFetch(textureSampler, ivec2(f_beg.x, f_beg.y), 0);
|
||||
avg_color += area_ne * texelFetch(textureSampler, ivec2(f_end.x, f_beg.y), 0);
|
||||
avg_color += area_sw * texelFetch(textureSampler, ivec2(f_beg.x, f_end.y), 0);
|
||||
avg_color += area_se * texelFetch(textureSampler, ivec2(f_end.x, f_end.y), 0);
|
||||
|
||||
// Determine the size of the pixel box.
|
||||
int x_range = int(f_end.x - f_beg.x - 0.5);
|
||||
int y_range = int(f_end.y - f_beg.y - 0.5);
|
||||
|
||||
// Accumulate top and bottom edge pixels.
|
||||
for (int x = f_beg.x + 1; x <= f_beg.x + x_range; ++x) {
|
||||
avg_color += area_n * texelFetch(textureSampler, ivec2(x, f_beg.y), 0);
|
||||
avg_color += area_s * texelFetch(textureSampler, ivec2(x, f_end.y), 0);
|
||||
}
|
||||
|
||||
// Accumulate left and right edge pixels and all the pixels in between.
|
||||
for (int y = f_beg.y + 1; y <= f_beg.y + y_range; ++y) {
|
||||
avg_color += area_w * texelFetch(textureSampler, ivec2(f_beg.x, y), 0);
|
||||
avg_color += area_e * texelFetch(textureSampler, ivec2(f_end.x, y), 0);
|
||||
|
||||
for (int x = f_beg.x + 1; x <= f_beg.x + x_range; ++x) {
|
||||
avg_color += texelFetch(textureSampler, ivec2(x, y), 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the area of the pixel box that was sampled.
|
||||
float area_corners = area_nw + area_ne + area_sw + area_se;
|
||||
float area_edges = float(x_range) * (area_n + area_s) + float(y_range) * (area_w + area_e);
|
||||
float area_center = float(x_range) * float(y_range);
|
||||
|
||||
// Return the normalized average color.
|
||||
return avg_color / (area_corners + area_edges + area_center);
|
||||
}
|
||||
|
||||
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() {
|
||||
vec4 pixel = AreaSampling(color_texture, frag_tex_coord);
|
||||
if (convert_colors == 2){
|
||||
pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a);
|
||||
}
|
||||
color = pixel;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
//? #version 460
|
||||
layout(location = 0) in vec2 vert_position;
|
||||
layout(location = 1) in vec2 vert_tex_coord;
|
||||
layout(location = 0) out vec2 frag_tex_coord;
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
void main()
|
||||
{
|
||||
vec4 position = vec4(vert_position, 0.0, 1.0) * modelview_matrix;
|
||||
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright 2022 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
40
src/video_core/host_shaders/vulkan_simple_present.frag
Normal file
40
src/video_core/host_shaders/vulkan_simple_present.frag
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2022 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (location = 0) in vec2 frag_tex_coord;
|
||||
layout (location = 0) out vec4 color;
|
||||
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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() {
|
||||
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;
|
||||
}
|
||||
23
src/video_core/host_shaders/vulkan_simple_present.vert
Normal file
23
src/video_core/host_shaders/vulkan_simple_present.vert
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2022 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout (location = 0) in vec2 vert_position;
|
||||
layout (location = 1) in vec2 vert_tex_coord;
|
||||
layout (location = 0) out vec2 frag_tex_coord;
|
||||
|
||||
layout (push_constant, std140) uniform DrawInfo {
|
||||
mat4 modelview_matrix;
|
||||
vec4 i_resolution;
|
||||
vec4 o_resolution;
|
||||
int screen_id_l;
|
||||
int screen_id_r;
|
||||
int layer;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ void OGLTexture::Allocate(GLenum target, GLsizei levels, GLenum internalformat,
|
|||
glTexStorage3D(target, levels, internalformat, width, height, depth);
|
||||
break;
|
||||
}
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
#include "core/frontend/emu_window.h"
|
||||
#include "core/frontend/framebuffer_layout.h"
|
||||
#include "core/memory.h"
|
||||
#include "gl_state.h"
|
||||
#include "video_core/pica/pica_core.h"
|
||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||
#include "video_core/renderer_opengl/gl_state.h"
|
||||
#include "video_core/renderer_opengl/gl_texture_mailbox.h"
|
||||
#include "video_core/renderer_opengl/post_processing_opengl.h"
|
||||
|
|
@ -20,6 +22,39 @@
|
|||
#include "video_core/host_shaders/opengl_present_frag.h"
|
||||
#include "video_core/host_shaders/opengl_present_interlaced_frag.h"
|
||||
#include "video_core/host_shaders/opengl_present_vert.h"
|
||||
#include "video_core/host_shaders/opengl_simple_present_frag.h"
|
||||
#include "video_core/host_shaders/opengl_simple_present_vert.h"
|
||||
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_fxaa_frag.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_fxaa_vert.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass0_pre_frag.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass0_pre_vert.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass0_post_frag.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass0_post_vert.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass1_pre_frag.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass1_pre_vert.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass1_post_frag.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass1_post_vert.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass2_pre_frag.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass2_pre_vert.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass2_post_frag.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_pass2_post_vert.h"
|
||||
#include "video_core/host_shaders/antialiasing/OpenGL/opengl_smaa_hlsl.h"
|
||||
#include "video_core/host_shaders/antialiasing/AreaTex.h"
|
||||
#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 {
|
||||
|
||||
|
|
@ -315,12 +350,87 @@ void RendererOpenGL::LoadFBToScreenInfo(const Pica::FramebufferConfig& framebuff
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> flipVertically(const unsigned char* data, int width, int height, int channels)
|
||||
{
|
||||
int rowSize = width * channels;
|
||||
std::vector<unsigned char> flipped(width * height * channels);
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
const unsigned char* src = data + (height - 1 - y) * rowSize;
|
||||
unsigned char* dst = flipped.data() + y * rowSize;
|
||||
memcpy(dst, src, rowSize);
|
||||
}
|
||||
|
||||
return flipped;
|
||||
}
|
||||
|
||||
|
||||
void RendererOpenGL::AllocateSMAATextures(){
|
||||
//Load AreaTex and SearchTex to OGLTexture Objects
|
||||
areatex.Create();
|
||||
searchtex.Create();
|
||||
std::vector<unsigned char> areaTexBytes_Flipped = flipVertically(areaTexBytes, AREATEX_WIDTH, AREATEX_HEIGHT, 2);
|
||||
std::vector<unsigned char> searchTexBytes_Flipped = flipVertically(searchTexBytes, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 1);
|
||||
GLuint old_tex = OpenGLState::GetCurState().texture_units[0].texture_2d;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, areatex.handle);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT, 0, GL_RG, GL_UNSIGNED_BYTE, areaTexBytes_Flipped.data());
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, searchtex.handle);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 0, GL_RED, GL_UNSIGNED_BYTE, searchTexBytes_Flipped.data());
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, old_tex);
|
||||
}
|
||||
|
||||
void RendererOpenGL::AllocatePPTextures(){
|
||||
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the OpenGL state and creates persistent objects.
|
||||
*/
|
||||
void RendererOpenGL::InitOpenGLObjects() {
|
||||
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
||||
Settings::values.bg_blue.GetValue(), 1.0f);
|
||||
Settings::values.bg_blue.GetValue(), 0.0f);
|
||||
|
||||
for (std::size_t i = 0; i < samplers.size(); i++) {
|
||||
samplers[i].Create();
|
||||
|
|
@ -354,6 +464,10 @@ void RendererOpenGL::InitOpenGLObjects() {
|
|||
glEnableVertexAttribArray(attrib_position);
|
||||
glEnableVertexAttribArray(attrib_tex_coord);
|
||||
|
||||
// Allocate textures for Post Processing
|
||||
AllocateSMAATextures();
|
||||
textureFBO.Create();
|
||||
|
||||
// Allocate textures for each screen
|
||||
for (auto& screen_info : screen_infos) {
|
||||
screen_info.texture.resource.Create();
|
||||
|
|
@ -373,7 +487,7 @@ void RendererOpenGL::InitOpenGLObjects() {
|
|||
|
||||
screen_info.display_texture = screen_info.texture.resource.handle;
|
||||
}
|
||||
|
||||
AllocatePPTextures();
|
||||
state.texture_units[0].texture_2d = 0;
|
||||
state.Apply();
|
||||
}
|
||||
|
|
@ -411,30 +525,84 @@ void RendererOpenGL::ReloadShader(Settings::StereoRenderOption render_3d) {
|
|||
}
|
||||
}
|
||||
}
|
||||
shader.Create(HostShaders::OPENGL_PRESENT_VERT, shader_data);
|
||||
state.draw.shader_program = shader.handle;
|
||||
Present_shader.Create(HostShaders::OPENGL_PRESENT_VERT, shader_data);
|
||||
state.draw.shader_program = Present_shader.handle;
|
||||
AttachUniforms();
|
||||
|
||||
|
||||
// Setup FXAA, SMAA and Simple Present Shaders
|
||||
std::string FXAA_shader_data = fragment_shader_precision_OES;
|
||||
FXAA_shader_data += HostShaders::OPENGL_FXAA_FRAG;
|
||||
FXAA_shader.Create(HostShaders::OPENGL_FXAA_VERT, FXAA_shader_data);
|
||||
|
||||
std::string AREA_SAMPLING_shader_data = fragment_shader_precision_OES;
|
||||
AREA_SAMPLING_shader_data += HostShaders::OPENGL_AREA_SAMPLING_FRAG;
|
||||
AREA_SAMPLING_shader.Create(HostShaders::OPENGL_AREA_SAMPLING_VERT, AREA_SAMPLING_shader_data);
|
||||
|
||||
std::string SimplePresent_shader_data = fragment_shader_precision_OES;
|
||||
SimplePresent_shader_data += HostShaders::OPENGL_SIMPLE_PRESENT_FRAG;
|
||||
SimplePresent_shader.Create(HostShaders::OPENGL_SIMPLE_PRESENT_VERT, SimplePresent_shader_data);
|
||||
|
||||
std::string SMAA_PASS_0_shader_frag_data = fragment_shader_precision_OES;
|
||||
SMAA_PASS_0_shader_frag_data += HostShaders::OPENGL_SMAA_PASS0_PRE_FRAG;
|
||||
SMAA_PASS_0_shader_frag_data += HostShaders::OPENGL_SMAA_HLSL;
|
||||
SMAA_PASS_0_shader_frag_data += HostShaders::OPENGL_SMAA_PASS0_POST_FRAG;
|
||||
std::string SMAA_PASS_0_shader_vert_data;
|
||||
SMAA_PASS_0_shader_vert_data += HostShaders::OPENGL_SMAA_PASS0_PRE_VERT;
|
||||
SMAA_PASS_0_shader_vert_data += HostShaders::OPENGL_SMAA_HLSL;
|
||||
SMAA_PASS_0_shader_vert_data += HostShaders::OPENGL_SMAA_PASS0_POST_VERT;
|
||||
SMAA_PASS_0_shader.Create(SMAA_PASS_0_shader_vert_data, SMAA_PASS_0_shader_frag_data);
|
||||
|
||||
std::string SMAA_PASS_1_shader_frag_data = fragment_shader_precision_OES;
|
||||
SMAA_PASS_1_shader_frag_data += HostShaders::OPENGL_SMAA_PASS1_PRE_FRAG;
|
||||
SMAA_PASS_1_shader_frag_data += HostShaders::OPENGL_SMAA_HLSL;
|
||||
SMAA_PASS_1_shader_frag_data += HostShaders::OPENGL_SMAA_PASS1_POST_FRAG;
|
||||
std::string SMAA_PASS_1_shader_vert_data;
|
||||
SMAA_PASS_1_shader_vert_data += HostShaders::OPENGL_SMAA_PASS1_PRE_VERT;
|
||||
SMAA_PASS_1_shader_vert_data += HostShaders::OPENGL_SMAA_HLSL;
|
||||
SMAA_PASS_1_shader_vert_data += HostShaders::OPENGL_SMAA_PASS1_POST_VERT;
|
||||
SMAA_PASS_1_shader.Create(SMAA_PASS_1_shader_vert_data, SMAA_PASS_1_shader_frag_data);
|
||||
|
||||
std::string SMAA_PASS_2_shader_frag_data = fragment_shader_precision_OES;
|
||||
SMAA_PASS_2_shader_frag_data += HostShaders::OPENGL_SMAA_PASS2_PRE_FRAG;
|
||||
SMAA_PASS_2_shader_frag_data += HostShaders::OPENGL_SMAA_HLSL;
|
||||
SMAA_PASS_2_shader_frag_data += HostShaders::OPENGL_SMAA_PASS2_POST_FRAG;
|
||||
std::string SMAA_PASS_2_shader_vert_data;
|
||||
SMAA_PASS_2_shader_vert_data += HostShaders::OPENGL_SMAA_PASS2_PRE_VERT;
|
||||
SMAA_PASS_2_shader_vert_data += HostShaders::OPENGL_SMAA_HLSL;
|
||||
SMAA_PASS_2_shader_vert_data += HostShaders::OPENGL_SMAA_PASS2_POST_VERT;
|
||||
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();
|
||||
uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix");
|
||||
uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture");
|
||||
if (render_3d == Settings::StereoRenderOption::Anaglyph ||
|
||||
render_3d == Settings::StereoRenderOption::Interlaced ||
|
||||
render_3d == Settings::StereoRenderOption::ReverseInterlaced) {
|
||||
uniform_color_texture_r = glGetUniformLocation(shader.handle, "color_texture_r");
|
||||
}
|
||||
if (render_3d == Settings::StereoRenderOption::Interlaced ||
|
||||
render_3d == Settings::StereoRenderOption::ReverseInterlaced) {
|
||||
GLuint uniform_reverse_interlaced =
|
||||
glGetUniformLocation(shader.handle, "reverse_interlaced");
|
||||
if (render_3d == Settings::StereoRenderOption::ReverseInterlaced)
|
||||
glUniform1i(uniform_reverse_interlaced, 1);
|
||||
else
|
||||
glUniform1i(uniform_reverse_interlaced, 0);
|
||||
}
|
||||
uniform_i_resolution = glGetUniformLocation(shader.handle, "i_resolution");
|
||||
uniform_o_resolution = glGetUniformLocation(shader.handle, "o_resolution");
|
||||
uniform_layer = glGetUniformLocation(shader.handle, "layer");
|
||||
attrib_position = glGetAttribLocation(shader.handle, "vert_position");
|
||||
attrib_tex_coord = glGetAttribLocation(shader.handle, "vert_tex_coord");
|
||||
}
|
||||
|
||||
void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
|
||||
|
|
@ -505,69 +673,520 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
|
|||
state.Apply();
|
||||
}
|
||||
|
||||
void RendererOpenGL::AttachUniforms(){
|
||||
uniform_modelview_matrix = glGetUniformLocation(state.draw.shader_program, "modelview_matrix");
|
||||
uniform_color_texture = glGetUniformLocation(state.draw.shader_program, "color_texture");
|
||||
uniform_color_texture_r = glGetUniformLocation(state.draw.shader_program, "color_texture_r");
|
||||
uniform_reverse_interlaced = glGetUniformLocation(state.draw.shader_program, "reverse_interlaced");
|
||||
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");
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD
|
||||
* rotation.
|
||||
*/
|
||||
void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w,
|
||||
float h, Layout::DisplayOrientation orientation) {
|
||||
void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float screenLeft, float screenTop, float screenWidth,
|
||||
float screenHeight, Layout::DisplayOrientation orientation) {
|
||||
const auto& texcoords = screen_info.display_texcoords;
|
||||
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){
|
||||
currScreen = 0;
|
||||
} else {
|
||||
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 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;
|
||||
}
|
||||
} else {
|
||||
if (textureWidth > screenHeight){
|
||||
isDownsampling = true;
|
||||
}
|
||||
}
|
||||
// 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
|
||||
}};
|
||||
|
||||
std::array<ScreenRectVertex, 4> vertices;
|
||||
// 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
|
||||
}};
|
||||
|
||||
// Vertices for Azahar's Output Layout
|
||||
std::array<ScreenRectVertex, 4> output_vertices;
|
||||
switch (orientation) {
|
||||
case Layout::DisplayOrientation::Landscape:
|
||||
vertices = {{
|
||||
ScreenRectVertex(x, y, texcoords.bottom, texcoords.left),
|
||||
ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right),
|
||||
ScreenRectVertex(x, y + h, texcoords.top, texcoords.left),
|
||||
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.right),
|
||||
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
|
||||
}};
|
||||
break;
|
||||
case Layout::DisplayOrientation::Portrait:
|
||||
vertices = {{
|
||||
ScreenRectVertex(x, y, texcoords.bottom, texcoords.right),
|
||||
ScreenRectVertex(x + w, y, texcoords.top, texcoords.right),
|
||||
ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.left),
|
||||
ScreenRectVertex(x + w, y + h, texcoords.top, texcoords.left),
|
||||
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
|
||||
}};
|
||||
std::swap(h, w);
|
||||
std::swap(screenHeight, screenWidth);
|
||||
break;
|
||||
case Layout::DisplayOrientation::LandscapeFlipped:
|
||||
vertices = {{
|
||||
ScreenRectVertex(x, y, texcoords.top, texcoords.right),
|
||||
ScreenRectVertex(x + w, y, texcoords.top, texcoords.left),
|
||||
ScreenRectVertex(x, y + h, texcoords.bottom, texcoords.right),
|
||||
ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.left),
|
||||
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
|
||||
}};
|
||||
break;
|
||||
case Layout::DisplayOrientation::PortraitFlipped:
|
||||
vertices = {{
|
||||
ScreenRectVertex(x, y, texcoords.top, texcoords.left),
|
||||
ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.left),
|
||||
ScreenRectVertex(x, y + h, texcoords.top, texcoords.right),
|
||||
ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.right),
|
||||
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
|
||||
}};
|
||||
std::swap(h, w);
|
||||
std::swap(screenHeight, screenWidth);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Render_OpenGL, "Unknown DisplayOrientation: {}", orientation);
|
||||
break;
|
||||
}
|
||||
|
||||
const u32 scale_factor = GetResolutionScaleFactor();
|
||||
const GLuint sampler = samplers[Settings::values.filter_mode.GetValue()].handle;
|
||||
glUniform4f(uniform_i_resolution, static_cast<float>(screen_info.texture.width * scale_factor),
|
||||
static_cast<float>(screen_info.texture.height * scale_factor),
|
||||
1.0f / static_cast<float>(screen_info.texture.width * scale_factor),
|
||||
1.0f / static_cast<float>(screen_info.texture.height * scale_factor));
|
||||
glUniform4f(uniform_o_resolution, h, w, 1.0f / h, 1.0f / w);
|
||||
state.texture_units[0].texture_2d = screen_info.display_texture;
|
||||
state.texture_units[0].sampler = sampler;
|
||||
state.Apply();
|
||||
GLuint originalReadFramebuffer = state.draw.read_framebuffer;
|
||||
GLuint originalDrawFramebuffer = state.draw.draw_framebuffer;
|
||||
if (antialiasingMode == 1){
|
||||
//Pass 1
|
||||
state.draw.read_framebuffer = textureFBO.handle;
|
||||
state.draw.draw_framebuffer = textureFBO.handle;
|
||||
state.Apply();
|
||||
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][0].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SimplePresent_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
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, 0);
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(rotate_vertices), rotate_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
//Pass 2
|
||||
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, 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 = intermediateTextures[currScreen][0].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
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());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
} else if (antialiasingMode == 2){
|
||||
// Landscape Gamma Space Texture
|
||||
state.draw.read_framebuffer = textureFBO.handle;
|
||||
state.draw.draw_framebuffer = textureFBO.handle;
|
||||
state.Apply();
|
||||
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][0].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SimplePresent_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
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, 0);
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(rotate_vertices), rotate_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
// Landscape Linear Space Texture
|
||||
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][3].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SimplePresent_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
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);
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
// Edge Detection
|
||||
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][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 = 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);
|
||||
state.Apply();
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
// Blending Weight Calculation
|
||||
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][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 = 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;
|
||||
state.texture_units[2].texture_2d = searchtex.handle;
|
||||
state.texture_units[2].sampler = samplers[1].handle;
|
||||
GLuint uniform_areatex = glGetUniformLocation(state.draw.shader_program, "areaTex");
|
||||
GLuint uniform_searchtex = glGetUniformLocation(state.draw.shader_program, "searchTex");
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_areatex, 1);
|
||||
glUniform1i(uniform_searchtex, 2);
|
||||
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());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
// Neighborhood Blending
|
||||
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, 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 = intermediateTextures[currScreen][2].handle;
|
||||
state.texture_units[0].sampler = samplers[1].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);
|
||||
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());
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
} else {
|
||||
state.draw.read_framebuffer = textureFBO.handle;
|
||||
state.draw.draw_framebuffer = textureFBO.handle;
|
||||
state.Apply();
|
||||
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, antialiasFBOTexture[currScreen].handle, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
state.draw.shader_program = SimplePresent_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
state.texture_units[0].texture_2d = screen_info.display_texture;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
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);
|
||||
}
|
||||
if (scalingMode == 2){
|
||||
if (isDownsampling){
|
||||
//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 = AREA_SAMPLING_shader.handle;
|
||||
state.Apply();
|
||||
AttachUniforms();
|
||||
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);
|
||||
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;
|
||||
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 = antialiasFBOTexture[currScreen].handle;
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_convert_colors, 2);
|
||||
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 == 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;
|
||||
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 = antialiasFBOTexture[currScreen].handle;
|
||||
if (scalingMode == 1){
|
||||
state.texture_units[0].sampler = samplers[1].handle;
|
||||
} else {
|
||||
state.texture_units[0].sampler = samplers[0].handle;
|
||||
}
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
glUniform1i(uniform_convert_colors, 2);
|
||||
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);
|
||||
}
|
||||
state.texture_units[0].texture_2d = 0;
|
||||
state.texture_units[0].sampler = 0;
|
||||
state.Apply();
|
||||
|
|
@ -625,13 +1244,15 @@ 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),
|
||||
1.0f / static_cast<float>(screen_info_l.texture.width * scale_factor),
|
||||
1.0f / static_cast<float>(screen_info_l.texture.height * scale_factor));
|
||||
glUniform4f(uniform_o_resolution, h, w, 1.0f / h, 1.0f / w);
|
||||
glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data());
|
||||
state.texture_units[0].texture_2d = screen_info_l.display_texture;
|
||||
state.texture_units[1].texture_2d = screen_info_r.display_texture;
|
||||
state.texture_units[0].sampler = sampler;
|
||||
|
|
@ -655,12 +1276,12 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||
if (settings.bg_color_update_requested.exchange(false)) {
|
||||
// Update background color before drawing
|
||||
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
||||
Settings::values.bg_blue.GetValue(), 1.0f);
|
||||
Settings::values.bg_blue.GetValue(), 0.0f);
|
||||
}
|
||||
|
||||
if (settings.shader_update_requested.exchange(false)) {
|
||||
// Update fragment shader before drawing
|
||||
shader.Release();
|
||||
Present_shader.Release();
|
||||
// Link shaders and get variable locations
|
||||
ReloadShader(layout.render_3d_mode);
|
||||
}
|
||||
|
|
@ -668,15 +1289,46 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
|
|||
const auto& top_screen = layout.top_screen;
|
||||
const auto& bottom_screen = layout.bottom_screen;
|
||||
|
||||
glViewport(0, 0, layout.width, layout.height);
|
||||
// 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();
|
||||
// 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;
|
||||
state.viewport.width = layout.width;
|
||||
state.viewport.height = layout.height;
|
||||
originalViewport = {0, 0, static_cast<int>(layout.width), static_cast<int>(layout.height)};
|
||||
|
||||
state.Apply();
|
||||
|
||||
if (render_window.NeedsClearing()) {
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
// Set projection matrix
|
||||
std::array<GLfloat, 3 * 2> ortho_matrix =
|
||||
MakeOrthographicMatrix((float)layout.width, (float)layout.height, flipped);
|
||||
glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data());
|
||||
ortho_matrix = MakeOrthographicMatrix((float)layout.width, (float)layout.height, flipped);
|
||||
|
||||
// Bind texture in Texture Unit 0
|
||||
glUniform1i(uniform_color_texture, 0);
|
||||
|
|
@ -693,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);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "gl_resource_manager.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/renderer_opengl/frame_dumper_opengl.h"
|
||||
#include "video_core/renderer_opengl/gl_driver.h"
|
||||
|
|
@ -57,6 +58,9 @@ public:
|
|||
private:
|
||||
void InitOpenGLObjects();
|
||||
void ReloadShader(Settings::StereoRenderOption render_3d);
|
||||
void AllocateSMAATextures();
|
||||
void AllocatePPTextures();
|
||||
void AllocateOutputSizeTextures();
|
||||
void PrepareRendertarget();
|
||||
void RenderScreenshot();
|
||||
void RenderToMailbox(const Layout::FramebufferLayout& layout,
|
||||
|
|
@ -80,6 +84,8 @@ private:
|
|||
// Loads framebuffer from emulated memory into the display information structure
|
||||
void LoadFBToScreenInfo(const Pica::FramebufferConfig& framebuffer, ScreenInfo& screen_info,
|
||||
bool right_eye, const Pica::ColorFill& color_fill);
|
||||
// Attach Uniforms to the current shader
|
||||
void AttachUniforms();
|
||||
|
||||
private:
|
||||
Pica::PicaCore& pica;
|
||||
|
|
@ -90,17 +96,46 @@ private:
|
|||
// OpenGL object IDs
|
||||
OGLVertexArray vertex_array;
|
||||
OGLBuffer vertex_buffer;
|
||||
OGLProgram shader;
|
||||
OGLProgram Present_shader;
|
||||
OGLProgram SimplePresent_shader;
|
||||
OGLProgram FXAA_shader;
|
||||
OGLProgram SMAA_PASS_0_shader;
|
||||
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;
|
||||
//Textures for Top and Bottom Screen Respectively
|
||||
std::array<std::array<OGLTexture, 7>, 2> intermediateTextures;
|
||||
std::array<OGLTexture, 2> antialiasFBOTexture;
|
||||
|
||||
//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;
|
||||
|
||||
// Display information for top and bottom screens respectively
|
||||
std::array<ScreenInfo, 3> screen_infos;
|
||||
|
||||
std::array<GLfloat, 3 * 2> ortho_matrix;
|
||||
// Shader uniform location indices
|
||||
GLuint uniform_modelview_matrix;
|
||||
GLuint uniform_color_texture;
|
||||
GLuint uniform_color_texture_r;
|
||||
GLuint uniform_reverse_interlaced;
|
||||
|
||||
// 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;
|
||||
|
|
@ -112,6 +147,17 @@ private:
|
|||
GLuint attrib_tex_coord;
|
||||
|
||||
FrameDumperOpenGL frame_dumper;
|
||||
|
||||
// Variables tracking texture changes
|
||||
float prevTopTextureWidth;
|
||||
float prevTopTextureHeight;
|
||||
float prevBottomTextureWidth;
|
||||
float prevBottomTextureHeight;
|
||||
float currTopTextureWidth;
|
||||
float currTopTextureHeight;
|
||||
float currBottomTextureWidth;
|
||||
float currBottomTextureHeight;
|
||||
std::array<int, 4> originalViewport;
|
||||
};
|
||||
|
||||
} // namespace OpenGL
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
|
|
@ -62,13 +77,16 @@ struct PresentUniformData {
|
|||
int screen_id_r = 0;
|
||||
int layer = 0;
|
||||
int reverse_interlaced = 0;
|
||||
int convert_colors;
|
||||
};
|
||||
static_assert(sizeof(PresentUniformData) == 112,
|
||||
static_assert(sizeof(PresentUniformData) == 116,
|
||||
"PresentUniformData does not structure in shader!");
|
||||
|
||||
class RendererVulkan : public VideoCore::RendererBase {
|
||||
static constexpr std::size_t PRESENT_PIPELINES = 3;
|
||||
|
||||
static constexpr std::size_t POST_PIPELINES_SCREEN = 1;
|
||||
static constexpr std::size_t POST_PIPELINES_TEXTURE = 5;
|
||||
static constexpr std::size_t POST_SHADERS = 6;
|
||||
public:
|
||||
explicit RendererVulkan(Core::System& system, Pica::PicaCore& pica, Frontend::EmuWindow& window,
|
||||
Frontend::EmuWindow* secondary_window);
|
||||
|
|
@ -95,7 +113,18 @@ private:
|
|||
void RenderScreenshot();
|
||||
void RenderScreenshotWithStagingCopy();
|
||||
bool TryRenderScreenshotWithHostMemory();
|
||||
void PrepareDraw(Frame* frame, const Layout::FramebufferLayout& layout);
|
||||
// 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);
|
||||
|
||||
|
|
@ -110,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);
|
||||
|
||||
|
|
@ -118,6 +147,16 @@ private:
|
|||
bool right_eye);
|
||||
void FillScreen(Common::Vec3<u8> color, const TextureInfo& texture);
|
||||
|
||||
void AllocateTexture(TextureInfo& texture, int width, int height, vk::Format colorFormat);
|
||||
void CreateTextureFramebuffer(TextureInfo& texture, vk::Framebuffer& framebuffer);
|
||||
|
||||
// Create Renderpass used for Textures
|
||||
void CreateTextureRenderPass();
|
||||
// Allocate Post Processing Textures
|
||||
void AllocatePPTextures();
|
||||
// Create Framebuffers that are attached to the Post Processing Textures
|
||||
void CreatePPTextureFramebuffers();
|
||||
void AllocateSMAATextures();
|
||||
private:
|
||||
Memory::MemorySystem& memory;
|
||||
Pica::PicaCore& pica;
|
||||
|
|
@ -138,15 +177,61 @@ private:
|
|||
DescriptorHeap present_heap;
|
||||
vk::UniquePipelineLayout present_pipeline_layout;
|
||||
std::array<vk::Pipeline, PRESENT_PIPELINES> present_pipelines;
|
||||
// Post Processing Pipelines for use with RGBA16F Textures. Contains: Simple Present, FXAA, SMAA Pass 0, SMAA Pass 1, SMAA Pass 2
|
||||
std::array<vk::Pipeline, POST_PIPELINES_TEXTURE> post_pipelines_texture;
|
||||
// Post Processing Pipelines for presenting to screen. Contains: Area
|
||||
std::array<vk::Pipeline, POST_PIPELINES_SCREEN> post_pipelines_screen;
|
||||
std::array<vk::ShaderModule, PRESENT_PIPELINES> present_shaders;
|
||||
// Post Processing Shaders for use with RGBA16F Textures. Contains: Simple Present, FXAA, SMAA Pass 0, SMAA Pass 1, SMAA Pass 2
|
||||
std::array<vk::ShaderModule, POST_PIPELINES_TEXTURE> post_vert_shaders_texture;
|
||||
std::array<vk::ShaderModule, POST_PIPELINES_TEXTURE> post_frag_shaders_texture;
|
||||
// Post Processing Shaders for presenting to screen. Contains: Area
|
||||
std::array<vk::ShaderModule, POST_PIPELINES_SCREEN> post_vert_shaders_screen;
|
||||
std::array<vk::ShaderModule, POST_PIPELINES_SCREEN> post_frag_shaders_screen;
|
||||
// Linear and Nearest Sampler Respectively
|
||||
std::array<vk::Sampler, 2> present_samplers;
|
||||
vk::ShaderModule present_vertex_shader;
|
||||
u32 current_pipeline = 0;
|
||||
vk::ShaderModule simplepresent_vertex_shader;
|
||||
vk::ShaderModule simplepresent_frag_shader;
|
||||
vk::ShaderModule area_sampling_vertex_shader;
|
||||
vk::ShaderModule area_sampling_frag_shader;
|
||||
vk::ShaderModule fxaa_vertex_shader;
|
||||
vk::ShaderModule fxaa_frag_shader;
|
||||
vk::ShaderModule smaa_pass_0_vertex_shader;
|
||||
vk::ShaderModule smaa_pass_0_frag_shader;
|
||||
vk::ShaderModule smaa_pass_1_vertex_shader;
|
||||
vk::ShaderModule smaa_pass_1_frag_shader;
|
||||
vk::ShaderModule smaa_pass_2_vertex_shader;
|
||||
vk::ShaderModule smaa_pass_2_frag_shader;
|
||||
|
||||
// Renderpass for RGBA16F Textures
|
||||
vk::RenderPass textureRenderpass;
|
||||
|
||||
// Array of textures. 0 is top screen, 1 is bottom screen.
|
||||
std::array<std::array<TextureInfo, 5>, 2> intermediateTextures;
|
||||
std::array<TextureInfo, 2> antialiasTextures;
|
||||
|
||||
// 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;
|
||||
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{};
|
||||
|
||||
vk::ShaderModule cursor_vertex_shader{};
|
||||
vk::ShaderModule cursor_fragment_shader{};
|
||||
vk::Pipeline cursor_pipeline{};
|
||||
|
|
|
|||
|
|
@ -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