mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-05 18:23:39 -04:00
Merge 8d10a81ba4 into c03248f158
This commit is contained in:
commit
25198f8e71
92 changed files with 26756 additions and 270 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"
|
||||
|
|
|
|||
11
dist/qt_themes/default/style.qss
vendored
11
dist/qt_themes/default/style.qss
vendored
|
|
@ -28,6 +28,17 @@ QPushButton#TogglableStatusBarButton:hover {
|
|||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#StatusBarButton {
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
padding: 0px 3px 0px 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QPushButton#StatusBarButton:hover {
|
||||
border: 1px solid #76797C;
|
||||
}
|
||||
|
||||
QPushButton#button_reset_defaults {
|
||||
min-width: 57px;
|
||||
padding: 4px 8px;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ object SettingKeys {
|
|||
external fun frame_limit(): String
|
||||
external fun turbo_limit(): String
|
||||
external fun texture_filter(): String
|
||||
external fun antialiasing_filter(): String
|
||||
external fun fsr_sharpness(): String
|
||||
external fun output_scaling(): String
|
||||
external fun texture_sampling(): String
|
||||
external fun delay_game_render_thread_us(): String
|
||||
external fun simulate_3ds_gpu_timings(): String
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@ enum class IntSetting(
|
|||
PORTRAIT_BOTTOM_HEIGHT(SettingKeys.custom_portrait_bottom_height(),Settings.SECTION_LAYOUT,480),
|
||||
AUDIO_INPUT_TYPE(SettingKeys.input_type(), Settings.SECTION_AUDIO, 0),
|
||||
CPU_CLOCK_SPEED(SettingKeys.cpu_clock_percentage(), Settings.SECTION_CORE, 100),
|
||||
ANTIALIASING_FILTER(SettingKeys.antialiasing_filter(), Settings.SECTION_RENDERER, 0),
|
||||
FSR_SHARPNESS(SettingKeys.fsr_sharpness(), Settings.SECTION_RENDERER, 50),
|
||||
OUTPUT_SCALING(SettingKeys.output_scaling(), Settings.SECTION_RENDERER, 2),
|
||||
TEXTURE_FILTER(SettingKeys.texture_filter(), Settings.SECTION_RENDERER, 0),
|
||||
TEXTURE_SAMPLING(SettingKeys.texture_sampling(), Settings.SECTION_RENDERER, 0),
|
||||
USE_FRAME_LIMIT(SettingKeys.use_frame_limit(), Settings.SECTION_RENDERER, 1),
|
||||
|
|
|
|||
|
|
@ -931,14 +931,48 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||
)
|
||||
)
|
||||
add(
|
||||
SwitchSetting(
|
||||
BooleanSetting.LINEAR_FILTERING,
|
||||
R.string.linear_filtering,
|
||||
R.string.linear_filtering_description,
|
||||
BooleanSetting.LINEAR_FILTERING.key,
|
||||
BooleanSetting.LINEAR_FILTERING.defaultValue
|
||||
SingleChoiceSetting(
|
||||
IntSetting.OUTPUT_SCALING,
|
||||
R.string.output_scaling_name,
|
||||
R.string.output_scaling_description,
|
||||
R.array.outputScalingNames,
|
||||
R.array.outputScalingValues,
|
||||
IntSetting.OUTPUT_SCALING.key,
|
||||
IntSetting.OUTPUT_SCALING.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SliderSetting(
|
||||
IntSetting.FSR_SHARPNESS,
|
||||
R.string.fsr_sharpness_name,
|
||||
R.string.fsr_sharpness_description,
|
||||
0,
|
||||
100,
|
||||
"%",
|
||||
IntSetting.FSR_SHARPNESS.key,
|
||||
IntSetting.FSR_SHARPNESS.defaultValue.toFloat()
|
||||
)
|
||||
)
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.ANTIALIASING_FILTER,
|
||||
R.string.antialiasing_filter_name,
|
||||
R.string.antialiasing_filter_description,
|
||||
R.array.antialiasingFilterNames,
|
||||
R.array.antialiasingFilterValues,
|
||||
IntSetting.ANTIALIASING_FILTER.key,
|
||||
IntSetting.ANTIALIASING_FILTER.defaultValue
|
||||
)
|
||||
)
|
||||
// add(
|
||||
// SwitchSetting(
|
||||
// BooleanSetting.LINEAR_FILTERING,
|
||||
// R.string.linear_filtering,
|
||||
// R.string.linear_filtering_description,
|
||||
// BooleanSetting.LINEAR_FILTERING.key,
|
||||
// BooleanSetting.LINEAR_FILTERING.defaultValue
|
||||
// )
|
||||
// )
|
||||
add(
|
||||
SwitchSetting(
|
||||
BooleanSetting.SHADERS_ACCURATE_MUL,
|
||||
|
|
|
|||
|
|
@ -153,6 +153,9 @@ void Config::ReadValues() {
|
|||
ReadSetting("Renderer", Settings::values.use_disk_shader_cache);
|
||||
ReadSetting("Renderer", Settings::values.use_vsync);
|
||||
ReadSetting("Renderer", Settings::values.texture_filter);
|
||||
ReadSetting("Renderer", Settings::values.output_scaling);
|
||||
ReadSetting("Renderer", Settings::values.fsr_sharpness);
|
||||
ReadSetting("Renderer", Settings::values.antialiasing_filter);
|
||||
ReadSetting("Renderer", Settings::values.texture_sampling);
|
||||
ReadSetting("Renderer", Settings::values.turbo_limit);
|
||||
// Workaround to map Android setting for enabling the frame limiter to the format Citra expects
|
||||
|
|
|
|||
|
|
@ -190,6 +190,17 @@ static const char* android_config_default_file_content = (BOOST_HANA_STRING(R"(
|
|||
# Loaded from shaders/anaglyph
|
||||
)") DECLARE_KEY(anaglyph_shader_name) BOOST_HANA_STRING(R"(
|
||||
|
||||
# Scaling mode for image output
|
||||
# 0: Nearest, 1: Bilinear, 2 (default): Adaptive, 3: FSR 1, 4: Sharp Bilinear
|
||||
)") DECLARE_KEY(output_scaling) BOOST_HANA_STRING(R"(
|
||||
|
||||
# Antialiasing filter to use
|
||||
# 0 (default): None, 1: FXAA, 2: SMAA
|
||||
)") DECLARE_KEY(antialiasing_filter) BOOST_HANA_STRING(R"(
|
||||
|
||||
# 0 - 100: Strength of FSR Sharpening. 50 (default)
|
||||
)") DECLARE_KEY(fsr_sharpness) BOOST_HANA_STRING(R"(
|
||||
|
||||
# Whether to enable linear filtering or not
|
||||
# This is required for some shaders to work correctly
|
||||
# 0: Nearest, 1 (default): Linear
|
||||
|
|
|
|||
|
|
@ -297,6 +297,34 @@
|
|||
<item>5</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="outputScalingNames">
|
||||
<item>@string/nearest</item>
|
||||
<item>@string/bilinear</item>
|
||||
<item>@string/adaptive</item>
|
||||
<item>@string/fsr</item>
|
||||
<item>@string/sharpbilinear</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="outputScalingValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="antialiasingFilterNames">
|
||||
<item>@string/none</item>
|
||||
<item>@string/fxaa</item>
|
||||
<item>@string/smaa</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="antialiasingFilterValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="textureSamplingNames">
|
||||
<item>@string/game_controlled</item>
|
||||
<item>@string/nearest_neighbor</item>
|
||||
|
|
|
|||
|
|
@ -264,6 +264,12 @@
|
|||
<string name="use_integer_scaling_description">Scales the screens with an integer multiplier of the original 3DS screen. For layouts with two different screen sizes, the largest screen is integer-scaled.</string>
|
||||
<string name="texture_filter_name">Texture Filter</string>
|
||||
<string name="texture_filter_description">Enhances the visuals of applications by applying a filter to textures. The supported filters are Anime4K Ultrafast, Bicubic, ScaleForce, xBRZ freescale, and MMPX.</string>
|
||||
<string name="antialiasing_filter_name">Antialiasing Filter</string>
|
||||
<string name="antialiasing_filter_description">Reduces the amount of aliasing, resulting in smoother edges. FXAA is extremely lightweight but more aggressive and lower quality. SMAA is heavier but is higher quality and more selective with the edges it smooths.</string>
|
||||
<string name="output_scaling_name">Output Scaling</string>
|
||||
<string name="output_scaling_description">The method by which the game output is scaled to the screen. Nearest doesn\'t smooth visuals but causes uneven pixels at non-integer ratios. Bilinear smooths visuals but may cause aliasing when downscaling. Adaptive uses bilinear for upscaling, but uses area sampling to downscale without creating aliasing. FSR 1 is an upscaler which allows sharpening and allows better visuals without increasing the internal resolution, but needs to be used with antialiasing and a minimum internal resolution of 2x Native. Sharp Bilinear looks similar to nearest but is slightly smoothed to prevent uneven pixels at non-integer ratios.</string>
|
||||
<string name="fsr_sharpness_name">FSR Sharpness</string>
|
||||
<string name="fsr_sharpness_description">Specifies the strength of the sharpening pass when using FSR</string>
|
||||
<string name="delay_render_thread">Delay Game Render Thread</string>
|
||||
<string name="delay_render_thread_description">Delay the game render thread when it submits data to the GPU. Helps with performance issues in the (very few) applications with dynamic framerates.</string>
|
||||
<string name="simulate_3ds_gpu_timings">Simulate 3DS GPU Timings</string>
|
||||
|
|
@ -797,6 +803,18 @@
|
|||
<string name="xbrz">xBRZ</string>
|
||||
<string name="mmpx">MMPX</string>
|
||||
|
||||
<!-- Output scaling names -->
|
||||
<string name="nearest">Nearest</string>
|
||||
<string name="bilinear">Bilinear</string>
|
||||
<string name="adaptive">Adaptive</string>
|
||||
<string name="fsr">AMD FSR 1</string>
|
||||
<string name="sharpbilinear">Sharp Bilinear</string>
|
||||
|
||||
<!-- Antialiasing names -->
|
||||
<!-- None is already defined -->
|
||||
<string name="fxaa">FXAA</string>
|
||||
<string name="smaa">SMAA</string>
|
||||
|
||||
<!-- Texture Sampling names -->
|
||||
<string name="game_controlled">Game Controlled</string>
|
||||
<string name="nearest_neighbor">Nearest Neighbor</string>
|
||||
|
|
|
|||
|
|
@ -630,6 +630,23 @@ void GMainWindow::InitializeWidgets() {
|
|||
|
||||
statusBar()->insertPermanentWidget(0, graphics_api_button);
|
||||
|
||||
// Setup Output Scaling button
|
||||
output_scaling_button = new QPushButton();
|
||||
output_scaling_button->setObjectName(QStringLiteral("StatusBarButton"));
|
||||
output_scaling_button->setFocusPolicy(Qt::NoFocus);
|
||||
UpdateOutputScalingIndicator();
|
||||
connect(output_scaling_button, &QPushButton::clicked, this, [this] { UpdateOutputScalingIndicator(true); });
|
||||
statusBar()->insertPermanentWidget(1, output_scaling_button);
|
||||
|
||||
// Setup Antialiasing Filter button
|
||||
antialiasing_filter_button = new QPushButton();
|
||||
antialiasing_filter_button->setObjectName(QStringLiteral("StatusBarButton"));
|
||||
antialiasing_filter_button->setFocusPolicy(Qt::NoFocus);
|
||||
UpdateAntialiasingFilterIndicator();
|
||||
connect(antialiasing_filter_button, &QPushButton::clicked, this, [this] { UpdateAntialiasingFilterIndicator(true); });
|
||||
statusBar()->insertPermanentWidget(2, antialiasing_filter_button);
|
||||
|
||||
// Setup Volume button and slider
|
||||
volume_popup = new QWidget(this);
|
||||
volume_popup->setWindowFlags(Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint | Qt::Popup);
|
||||
volume_popup->setLayout(new QVBoxLayout());
|
||||
|
|
@ -660,7 +677,7 @@ void GMainWindow::InitializeWidgets() {
|
|||
bottomLeft.setY(bottomLeft.y() - volume_popup->geometry().height());
|
||||
volume_popup->setGeometry(QRect(bottomLeft, QSize(rect.width(), rect.height())));
|
||||
});
|
||||
statusBar()->insertPermanentWidget(1, volume_button);
|
||||
statusBar()->insertPermanentWidget(3, volume_button);
|
||||
|
||||
statusBar()->addPermanentWidget(multiplayer_state->GetStatusText());
|
||||
statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon());
|
||||
|
|
@ -3783,8 +3800,45 @@ void GMainWindow::UpdateAPIIndicator(bool update) {
|
|||
graphics_api_button->setStyleSheet(style_sheet);
|
||||
}
|
||||
|
||||
|
||||
void GMainWindow::UpdateOutputScalingIndicator(bool update) {
|
||||
static std::array output_scaling_options = {
|
||||
QStringLiteral("NEAREST"),
|
||||
QStringLiteral("BILINEAR"),
|
||||
QStringLiteral("ADAPTIVE"),
|
||||
QStringLiteral("FSR"),
|
||||
QStringLiteral("SHARP BILINEAR"),
|
||||
};
|
||||
|
||||
u32 selection_index = static_cast<u32>(Settings::values.output_scaling.GetValue());
|
||||
if (update) {
|
||||
selection_index = (selection_index + 1) % output_scaling_options.size();
|
||||
Settings::values.output_scaling = static_cast<Settings::OutputScaling>(selection_index);
|
||||
}
|
||||
|
||||
output_scaling_button->setText(output_scaling_options[selection_index]);
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateAntialiasingFilterIndicator(bool update) {
|
||||
static std::array antialiasing_filter_options = {
|
||||
QStringLiteral("NO AA"),
|
||||
QStringLiteral("FXAA"),
|
||||
QStringLiteral("SMAA"),
|
||||
};
|
||||
|
||||
u32 selection_index = static_cast<u32>(Settings::values.antialiasing_filter.GetValue());
|
||||
if (update) {
|
||||
selection_index = (selection_index + 1) % antialiasing_filter_options.size();
|
||||
Settings::values.antialiasing_filter = static_cast<Settings::AntiAliasingFilter>(selection_index);
|
||||
}
|
||||
|
||||
antialiasing_filter_button->setText(antialiasing_filter_options[selection_index]);
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateStatusButtons() {
|
||||
UpdateAPIIndicator();
|
||||
UpdateOutputScalingIndicator();
|
||||
UpdateAntialiasingFilterIndicator();
|
||||
UpdateVolumeUI();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -333,6 +333,8 @@ private:
|
|||
void OpenPerGameConfiguration(u64 title_id, const QString& file_name);
|
||||
void UpdateVolumeUI();
|
||||
void UpdateAPIIndicator(bool update = false);
|
||||
void UpdateOutputScalingIndicator(bool update = false);
|
||||
void UpdateAntialiasingFilterIndicator(bool update = false);
|
||||
void UpdateStatusButtons();
|
||||
#ifdef __unix__
|
||||
void SetGamemodeEnabled(bool state);
|
||||
|
|
@ -359,6 +361,8 @@ private:
|
|||
QLabel* emu_frametime_label = nullptr;
|
||||
QPushButton* graphics_api_button = nullptr;
|
||||
QPushButton* volume_button = nullptr;
|
||||
QPushButton* output_scaling_button = nullptr;
|
||||
QPushButton* antialiasing_filter_button = nullptr;
|
||||
QWidget* volume_popup = nullptr;
|
||||
QSlider* volume_slider = nullptr;
|
||||
QTimer status_bar_update_timer;
|
||||
|
|
|
|||
|
|
@ -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,75 @@ 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
|
||||
scaling/FSR/Vulkan/vulkan_fsr_pass0.vert
|
||||
scaling/FSR/Vulkan/vulkan_fsr_pass0_part1.frag
|
||||
scaling/FSR/Vulkan/vulkan_fsr_pass0_part2.frag
|
||||
scaling/FSR/Vulkan/vulkan_fsr_pass1.vert
|
||||
scaling/FSR/Vulkan/vulkan_fsr_pass1_part1.frag
|
||||
scaling/FSR/Vulkan/vulkan_fsr_pass1_part2.frag
|
||||
scaling/FSR/Vulkan/vulkan_fsr_pass1_part3.frag
|
||||
scaling/SharpBilinear/Vulkan/vulkan_sharpbilinear.vert
|
||||
scaling/SharpBilinear/Vulkan/vulkan_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);
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// FSR - [EASU] EDGE ADAPTIVE SPATIAL UPSAMPLING
|
||||
// SM 4.0 compatible: no textureGather, direct texelFetch of 12 unique texels.
|
||||
#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;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// FSR - [EASU] EDGE ADAPTIVE SPATIAL UPSAMPLING
|
||||
// SM 4.0 compatible: no textureGather, direct texelFetch of 12 unique texels.
|
||||
#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;
|
||||
};
|
||||
|
||||
#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,26 @@
|
|||
// FSR - [RCAS] ROBUST CONTRAST ADAPTIVE SHARPENING
|
||||
//? #version 450
|
||||
#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;
|
||||
int reverse_interlaced;
|
||||
int convert_colors;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vert_position, 0.0, 1.0);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// FSR - [RCAS] ROBUST CONTRAST ADAPTIVE SHARPENING
|
||||
#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;
|
||||
float FSR_SHARPENING;
|
||||
};
|
||||
|
||||
#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,61 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
#version 450 core
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
|
||||
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 (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;
|
||||
};
|
||||
|
||||
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,27 @@
|
|||
#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(location = 1) out vec2 precalc_texel;
|
||||
layout(location = 2) out vec2 precalc_scale;
|
||||
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;
|
||||
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(float(f_end.x) - float(f_beg.x) - 0.5);
|
||||
int y_range = int(float(f_end.y) - float(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;
|
||||
}
|
||||
|
||||
102
src/video_core/host_shaders/scaling/vulkan_area_sampling.frag
Normal file
102
src/video_core/host_shaders/scaling/vulkan_area_sampling.frag
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
//? #version 460 core
|
||||
#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;
|
||||
};
|
||||
|
||||
/***** 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,24 @@
|
|||
//? #version 460
|
||||
#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;
|
||||
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 {
|
||||
|
||||
|
|
@ -103,6 +138,7 @@ void RendererOpenGL::SwapBuffers() {
|
|||
render_window.SwapBuffers();
|
||||
#else
|
||||
const auto& main_layout = render_window.GetFramebufferLayout();
|
||||
isSecondaryWindow = false;
|
||||
RenderToMailbox(main_layout, render_window.mailbox, false);
|
||||
|
||||
#ifdef ANDROID
|
||||
|
|
@ -110,6 +146,7 @@ void RendererOpenGL::SwapBuffers() {
|
|||
// it means we have a second display
|
||||
if (secondary_window) {
|
||||
const auto& secondary_layout = secondary_window->GetFramebufferLayout();
|
||||
isSecondaryWindow = true;
|
||||
RenderToMailbox(secondary_layout, secondary_window->mailbox, false);
|
||||
secondary_window->PollEvents();
|
||||
}
|
||||
|
|
@ -117,6 +154,7 @@ void RendererOpenGL::SwapBuffers() {
|
|||
if (Settings::values.layout_option.GetValue() == Settings::LayoutOption::SeparateWindows) {
|
||||
ASSERT(secondary_window);
|
||||
const auto& secondary_layout = secondary_window->GetFramebufferLayout();
|
||||
isSecondaryWindow = true;
|
||||
RenderToMailbox(secondary_layout, secondary_window->mailbox, false);
|
||||
secondary_window->PollEvents();
|
||||
}
|
||||
|
|
@ -315,12 +353,94 @@ 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[isSecondaryWindow].size(); i++){
|
||||
if (currOutputScreenRects[isSecondaryWindow][i].GetHeight() != 0 && currOutputScreenRects[isSecondaryWindow][i].GetWidth() != 0){
|
||||
for (int j = 0; j < intermediateOutputSizeTextures[isSecondaryWindow][0].size(); j++){
|
||||
intermediateOutputSizeTextures[isSecondaryWindow][i][j].Release();
|
||||
intermediateOutputSizeTextures[isSecondaryWindow][i][j].Create();
|
||||
intermediateOutputSizeTextures[isSecondaryWindow][i][j].Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, currOutputScreenRects[isSecondaryWindow][i].GetWidth(), currOutputScreenRects[isSecondaryWindow][i].GetHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO(Render_OpenGL, "Reallocated OutputSize Textures.\nPrevRects:\n{}x{}\n{}x{}\n{}x{}\nCurrRects:\n{}x{}\n{}x{}\n{}x{}",
|
||||
prevOutputScreenRects[isSecondaryWindow][0].GetWidth(), prevOutputScreenRects[isSecondaryWindow][0].GetHeight(),
|
||||
prevOutputScreenRects[isSecondaryWindow][1].GetWidth(), prevOutputScreenRects[isSecondaryWindow][1].GetHeight(),
|
||||
prevOutputScreenRects[isSecondaryWindow][2].GetWidth(), prevOutputScreenRects[isSecondaryWindow][2].GetHeight(),
|
||||
currOutputScreenRects[isSecondaryWindow][0].GetWidth(), currOutputScreenRects[isSecondaryWindow][0].GetHeight(),
|
||||
currOutputScreenRects[isSecondaryWindow][1].GetWidth(), currOutputScreenRects[isSecondaryWindow][1].GetHeight(),
|
||||
currOutputScreenRects[isSecondaryWindow][2].GetWidth(), currOutputScreenRects[isSecondaryWindow][2].GetHeight()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 +474,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 +497,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 +535,86 @@ 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);
|
||||
|
||||
std::string SharpBilinear_shader_frag_data = fragment_shader_precision_OES;
|
||||
SharpBilinear_shader_frag_data += HostShaders::OPENGL_SHARPBILINEAR_FRAG;
|
||||
SharpBilinear_shader.Create(HostShaders::OPENGL_SHARPBILINEAR_VERT, SharpBilinear_shader_frag_data);
|
||||
|
||||
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 +685,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[isSecondaryWindow][currOutputScreen][0].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[isSecondaryWindow][currOutputScreen][1].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[isSecondaryWindow][currOutputScreen][0].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[isSecondaryWindow][currOutputScreen][1].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 +1256,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 +1288,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 +1301,52 @@ 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[isSecondaryWindow][0] = layout.top_screen;
|
||||
currOutputScreenRects[isSecondaryWindow][1] = layout.bottom_screen;
|
||||
currOutputScreenRects[isSecondaryWindow][2] = layout.additional_screen;
|
||||
if (currOutputScreenRects[isSecondaryWindow][0] != prevOutputScreenRects[isSecondaryWindow][0] || currOutputScreenRects[isSecondaryWindow][1] != prevOutputScreenRects[isSecondaryWindow][1]){
|
||||
if (layout.additional_screen_enabled){
|
||||
if (currOutputScreenRects[isSecondaryWindow][2] != prevOutputScreenRects[isSecondaryWindow][2]){
|
||||
AllocateOutputSizeTextures();
|
||||
}
|
||||
} else {
|
||||
AllocateOutputSizeTextures();
|
||||
}
|
||||
}
|
||||
prevOutputScreenRects[isSecondaryWindow][0] = currOutputScreenRects[isSecondaryWindow][0];
|
||||
prevOutputScreenRects[isSecondaryWindow][1] = currOutputScreenRects[isSecondaryWindow][1];
|
||||
prevOutputScreenRects[isSecondaryWindow][2] = currOutputScreenRects[isSecondaryWindow][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 +1363,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<std::array<OGLTexture, 3>, 3>, 2> intermediateOutputSizeTextures;
|
||||
std::array<std::array<Common::Rectangle<u32>, 3>, 2> prevOutputScreenRects;
|
||||
std::array<std::array<Common::Rectangle<u32>, 3>, 2> 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,21 @@ 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;
|
||||
|
||||
// Secondary Layout Fix
|
||||
bool isSecondaryWindow;
|
||||
|
||||
};
|
||||
|
||||
} // namespace OpenGL
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -48,6 +48,36 @@ struct TextureInfo {
|
|||
VmaAllocation allocation;
|
||||
};
|
||||
|
||||
struct StagedTextureInfo {
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 channels;
|
||||
u32 size;
|
||||
Pica::PixelFormat format;
|
||||
vk::Buffer buffer;
|
||||
VmaAllocation bufferAllocation;
|
||||
vk::Image image;
|
||||
vk::ImageView image_view;
|
||||
VmaAllocation imageAllocation;
|
||||
void* bufferDataPtr;
|
||||
TextureInfo texInfo;
|
||||
};
|
||||
|
||||
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 +92,16 @@ struct PresentUniformData {
|
|||
int screen_id_r = 0;
|
||||
int layer = 0;
|
||||
int reverse_interlaced = 0;
|
||||
int convert_colors;
|
||||
float FSR_SHARPENING;
|
||||
};
|
||||
static_assert(sizeof(PresentUniformData) == 112,
|
||||
static_assert(sizeof(PresentUniformData) == 120,
|
||||
"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 = 2;
|
||||
static constexpr std::size_t POST_PIPELINES_TEXTURE = 7;
|
||||
public:
|
||||
explicit RendererVulkan(Core::System& system, Pica::PicaCore& pica, Frontend::EmuWindow& window,
|
||||
Frontend::EmuWindow* secondary_window);
|
||||
|
|
@ -95,7 +128,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 PrepareTextureDrawFromTextureInfo(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 +154,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 +162,23 @@ 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 AllocateStagedTexture(StagedTextureInfo& 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 AllocateSMAATextures();
|
||||
void UploadImageDataToBuffer(StagedTextureInfo& texture, unsigned char* imageData);
|
||||
void CreateImageStagingBuffer(StagedTextureInfo& texture);
|
||||
void UploadBufferToImage(StagedTextureInfo& texture);
|
||||
void AllocatePPTextures();
|
||||
void AllocateOutputSizeTextures();
|
||||
// Create Framebuffers that are attached to the Post Processing Textures
|
||||
void CreatePPTextureFramebuffers();
|
||||
void CreateOutputSizeTextureFramebuffers();
|
||||
void SetStagedTextureTexInfo(StagedTextureInfo& texture);
|
||||
private:
|
||||
Memory::MemorySystem& memory;
|
||||
Pica::PicaCore& pica;
|
||||
|
|
@ -138,19 +199,78 @@ 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, FSR Pass 0, FSR Pass 1
|
||||
std::array<vk::Pipeline, POST_PIPELINES_TEXTURE> post_pipelines_texture;
|
||||
// Post Processing Pipelines for presenting to screen. Contains: Area Sampling and Sharp Bilinear
|
||||
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, FSR Pass 0, FSR Pass 1
|
||||
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 Sampling and Sharp Bilinear
|
||||
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;
|
||||
StagedTextureInfo areaTexInfo;
|
||||
StagedTextureInfo searchTexInfo;
|
||||
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, 7>, 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, 7>, 2> intermediateTextureFBOs;
|
||||
std::array<vk::Framebuffer, 2 > antialiasTextureFBOs;
|
||||
std::array<std::array<std::array<TextureInfo, 3>, 3>, 2> intermediateOutputSizeTextures;
|
||||
std::array<std::array<std::array<vk::Framebuffer, 3>, 3>, 2> intermediateOutputSizeTextureFBOs;
|
||||
std::array<std::array<Common::Rectangle<u32>, 3>, 2> prevOutputScreenRects;
|
||||
std::array<std::array<Common::Rectangle<u32>, 3>, 2> currOutputScreenRects;
|
||||
int currOutputScreen;
|
||||
float currTopTextureWidth;
|
||||
float currTopTextureHeight;
|
||||
float currBottomTextureWidth;
|
||||
float currBottomTextureHeight;
|
||||
float prevTopTextureWidth;
|
||||
float prevTopTextureHeight;
|
||||
float prevBottomTextureWidth;
|
||||
float prevBottomTextureHeight;
|
||||
int currentPass = 0;
|
||||
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{};
|
||||
vk::UniquePipelineLayout cursor_pipeline_layout{};
|
||||
|
||||
// Secondary Layout Fix
|
||||
bool isSecondaryWindow;
|
||||
bool secondaryWindowEnabled;
|
||||
bool usingAndroid;
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -489,7 +490,7 @@ void PresentWindow::CopyToSwapchain(Frame* frame) {
|
|||
vk::RenderPass PresentWindow::CreateRenderpass() {
|
||||
const vk::AttachmentReference color_ref = {
|
||||
.attachment = 0,
|
||||
.layout = vk::ImageLayout::eGeneral,
|
||||
.layout = vk::ImageLayout::eColorAttachmentOptimal,
|
||||
};
|
||||
|
||||
const vk::SubpassDescription subpass = {
|
||||
|
|
@ -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::eColorAttachmentOptimal,
|
||||
};
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -6,15 +6,17 @@
|
|||
|
||||
// High precision may or may not be supported in GLES3. If it isn't, use medium precision instead.
|
||||
static constexpr char fragment_shader_precision_OES[] = R"(
|
||||
#if GL_ES
|
||||
#ifdef GL_ES
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
||||
precision highp int;
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
precision highp samplerBuffer;
|
||||
precision highp uimage2D;
|
||||
#else
|
||||
precision mediump int;
|
||||
precision mediump float;
|
||||
precision highp sampler2D;
|
||||
precision mediump samplerBuffer;
|
||||
precision mediump uimage2D;
|
||||
#endif // GL_FRAGMENT_PRECISION_HIGH
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue