mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-02-01 04:05:38 +00:00
GPU/HW: Add separate 3D/2D (sprite) texture filtering
This commit is contained in:
parent
be4abb016f
commit
34f20798a1
|
@ -479,7 +479,8 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes
|
||||||
|
|
||||||
if (HasTrait(Trait::DisableTextureFiltering))
|
if (HasTrait(Trait::DisableTextureFiltering))
|
||||||
{
|
{
|
||||||
if (display_osd_messages && settings.gpu_texture_filter != GPUTextureFilter::Nearest)
|
if (display_osd_messages && (settings.gpu_texture_filter != GPUTextureFilter::Nearest ||
|
||||||
|
g_settings.gpu_sprite_texture_filter != GPUTextureFilter::Nearest))
|
||||||
{
|
{
|
||||||
Host::AddIconOSDMessage("gamedb_disable_upscaling", ICON_FA_MAGIC,
|
Host::AddIconOSDMessage("gamedb_disable_upscaling", ICON_FA_MAGIC,
|
||||||
TRANSLATE_STR("OSDMessage", "Texture filtering disabled by compatibility settings."),
|
TRANSLATE_STR("OSDMessage", "Texture filtering disabled by compatibility settings."),
|
||||||
|
@ -487,6 +488,7 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.gpu_texture_filter = GPUTextureFilter::Nearest;
|
settings.gpu_texture_filter = GPUTextureFilter::Nearest;
|
||||||
|
settings.gpu_sprite_texture_filter = GPUTextureFilter::Nearest;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasTrait(Trait::DisableScaledDithering))
|
if (HasTrait(Trait::DisableScaledDithering))
|
||||||
|
|
|
@ -59,10 +59,17 @@ ALWAYS_INLINE_RELEASE static u32 GetBoxDownsampleScale(u32 resolution_scale)
|
||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE static bool ShouldClampUVs()
|
ALWAYS_INLINE static bool ShouldClampUVs(GPUTextureFilter texture_filter)
|
||||||
{
|
{
|
||||||
// We only need UV limits if PGXP is enabled, or texture filtering is enabled.
|
// We only need UV limits if PGXP is enabled, or texture filtering is enabled.
|
||||||
return g_settings.gpu_pgxp_enable || g_settings.gpu_texture_filter != GPUTextureFilter::Nearest;
|
return g_settings.gpu_pgxp_enable || texture_filter != GPUTextureFilter::Nearest;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE static bool ShouldAllowSpriteMode(u8 resolution_scale, GPUTextureFilter texture_filter,
|
||||||
|
GPUTextureFilter sprite_texture_filter)
|
||||||
|
{
|
||||||
|
// Use sprite shaders/mode when texcoord rounding is forced, or if the filters are different.
|
||||||
|
return (sprite_texture_filter != texture_filter || (resolution_scale > 1 && g_settings.gpu_force_round_texcoords));
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE static bool ShouldDisableColorPerspective()
|
ALWAYS_INLINE static bool ShouldDisableColorPerspective()
|
||||||
|
@ -73,7 +80,16 @@ ALWAYS_INLINE static bool ShouldDisableColorPerspective()
|
||||||
/// Returns true if the specified texture filtering mode requires dual-source blending.
|
/// Returns true if the specified texture filtering mode requires dual-source blending.
|
||||||
ALWAYS_INLINE static bool IsBlendedTextureFiltering(GPUTextureFilter filter)
|
ALWAYS_INLINE static bool IsBlendedTextureFiltering(GPUTextureFilter filter)
|
||||||
{
|
{
|
||||||
return (filter == GPUTextureFilter::Bilinear || filter == GPUTextureFilter::JINC2 || filter == GPUTextureFilter::xBR);
|
// return (filter == GPUTextureFilter::Bilinear || filter == GPUTextureFilter::JINC2 || filter ==
|
||||||
|
// GPUTextureFilter::xBR);
|
||||||
|
static_assert(((static_cast<u8>(GPUTextureFilter::Nearest) & 1u) == 0u) &&
|
||||||
|
((static_cast<u8>(GPUTextureFilter::Bilinear) & 1u) == 1u) &&
|
||||||
|
((static_cast<u8>(GPUTextureFilter::BilinearBinAlpha) & 1u) == 0u) &&
|
||||||
|
((static_cast<u8>(GPUTextureFilter::JINC2) & 1u) == 1u) &&
|
||||||
|
((static_cast<u8>(GPUTextureFilter::JINC2BinAlpha) & 1u) == 0u) &&
|
||||||
|
((static_cast<u8>(GPUTextureFilter::xBR) & 1u) == 1u) &&
|
||||||
|
((static_cast<u8>(GPUTextureFilter::xBRBinAlpha) & 1u) == 0u));
|
||||||
|
return ((static_cast<u8>(filter) & 1u) == 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the area affected by a VRAM transfer, including wrap-around of X.
|
/// Computes the area affected by a VRAM transfer, including wrap-around of X.
|
||||||
|
@ -193,17 +209,18 @@ bool GPU_HW::Initialize()
|
||||||
|
|
||||||
m_resolution_scale = Truncate8(CalculateResolutionScale());
|
m_resolution_scale = Truncate8(CalculateResolutionScale());
|
||||||
m_multisamples = Truncate8(std::min<u32>(g_settings.gpu_multisamples, g_gpu_device->GetMaxMultisamples()));
|
m_multisamples = Truncate8(std::min<u32>(g_settings.gpu_multisamples, g_gpu_device->GetMaxMultisamples()));
|
||||||
|
m_texture_filtering = g_settings.gpu_texture_filter;
|
||||||
|
m_sprite_texture_filtering = g_settings.gpu_sprite_texture_filter;
|
||||||
|
m_line_detect_mode = (m_resolution_scale > 1) ? g_settings.gpu_line_detect_mode : GPULineDetectMode::Disabled;
|
||||||
|
m_downsample_mode = GetDownsampleMode(m_resolution_scale);
|
||||||
|
m_wireframe_mode = g_settings.gpu_wireframe_mode;
|
||||||
m_supports_dual_source_blend = features.dual_source_blend;
|
m_supports_dual_source_blend = features.dual_source_blend;
|
||||||
m_supports_framebuffer_fetch = features.framebuffer_fetch;
|
m_supports_framebuffer_fetch = features.framebuffer_fetch;
|
||||||
m_true_color = g_settings.gpu_true_color;
|
m_true_color = g_settings.gpu_true_color;
|
||||||
|
|
||||||
m_texture_filtering = g_settings.gpu_texture_filter;
|
|
||||||
m_line_detect_mode = (m_resolution_scale > 1) ? g_settings.gpu_line_detect_mode : GPULineDetectMode::Disabled;
|
|
||||||
m_clamp_uvs = ShouldClampUVs();
|
|
||||||
m_compute_uv_range = m_clamp_uvs;
|
|
||||||
m_downsample_mode = GetDownsampleMode(m_resolution_scale);
|
|
||||||
m_wireframe_mode = g_settings.gpu_wireframe_mode;
|
|
||||||
m_pgxp_depth_buffer = g_settings.UsingPGXPDepthBuffer();
|
m_pgxp_depth_buffer = g_settings.UsingPGXPDepthBuffer();
|
||||||
|
m_clamp_uvs = ShouldClampUVs(m_texture_filtering) || ShouldClampUVs(m_sprite_texture_filtering);
|
||||||
|
m_compute_uv_range = m_clamp_uvs;
|
||||||
|
m_allow_sprite_mode = ShouldAllowSpriteMode(m_resolution_scale, m_texture_filtering, m_sprite_texture_filtering);
|
||||||
|
|
||||||
CheckSettings();
|
CheckSettings();
|
||||||
|
|
||||||
|
@ -317,7 +334,7 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
||||||
|
|
||||||
const u8 resolution_scale = Truncate8(CalculateResolutionScale());
|
const u8 resolution_scale = Truncate8(CalculateResolutionScale());
|
||||||
const u8 multisamples = Truncate8(std::min<u32>(g_settings.gpu_multisamples, g_gpu_device->GetMaxMultisamples()));
|
const u8 multisamples = Truncate8(std::min<u32>(g_settings.gpu_multisamples, g_gpu_device->GetMaxMultisamples()));
|
||||||
const bool clamp_uvs = ShouldClampUVs();
|
const bool clamp_uvs = ShouldClampUVs(m_texture_filtering) || ShouldClampUVs(m_sprite_texture_filtering);
|
||||||
const bool framebuffer_changed =
|
const bool framebuffer_changed =
|
||||||
(m_resolution_scale != resolution_scale || m_multisamples != multisamples ||
|
(m_resolution_scale != resolution_scale || m_multisamples != multisamples ||
|
||||||
(static_cast<bool>(m_vram_depth_texture) != (g_settings.UsingPGXPDepthBuffer() || !m_supports_framebuffer_fetch)));
|
(static_cast<bool>(m_vram_depth_texture) != (g_settings.UsingPGXPDepthBuffer() || !m_supports_framebuffer_fetch)));
|
||||||
|
@ -328,14 +345,17 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
||||||
(resolution_scale > 1 && g_settings.gpu_scaled_dithering != old_settings.gpu_scaled_dithering) ||
|
(resolution_scale > 1 && g_settings.gpu_scaled_dithering != old_settings.gpu_scaled_dithering) ||
|
||||||
(resolution_scale > 1 && g_settings.gpu_texture_filter == GPUTextureFilter::Nearest &&
|
(resolution_scale > 1 && g_settings.gpu_texture_filter == GPUTextureFilter::Nearest &&
|
||||||
g_settings.gpu_force_round_texcoords != old_settings.gpu_force_round_texcoords) ||
|
g_settings.gpu_force_round_texcoords != old_settings.gpu_force_round_texcoords) ||
|
||||||
m_texture_filtering != g_settings.gpu_texture_filter || m_clamp_uvs != clamp_uvs ||
|
m_texture_filtering != g_settings.gpu_texture_filter ||
|
||||||
|
m_sprite_texture_filtering != g_settings.gpu_sprite_texture_filter || m_clamp_uvs != clamp_uvs ||
|
||||||
(resolution_scale > 1 && (g_settings.gpu_downsample_mode != old_settings.gpu_downsample_mode ||
|
(resolution_scale > 1 && (g_settings.gpu_downsample_mode != old_settings.gpu_downsample_mode ||
|
||||||
(m_downsample_mode == GPUDownsampleMode::Box &&
|
(m_downsample_mode == GPUDownsampleMode::Box &&
|
||||||
g_settings.gpu_downsample_scale != old_settings.gpu_downsample_scale))) ||
|
g_settings.gpu_downsample_scale != old_settings.gpu_downsample_scale))) ||
|
||||||
(features.geometry_shaders && g_settings.gpu_wireframe_mode != old_settings.gpu_wireframe_mode) ||
|
(features.geometry_shaders && g_settings.gpu_wireframe_mode != old_settings.gpu_wireframe_mode) ||
|
||||||
m_pgxp_depth_buffer != g_settings.UsingPGXPDepthBuffer() ||
|
m_pgxp_depth_buffer != g_settings.UsingPGXPDepthBuffer() ||
|
||||||
(features.noperspective_interpolation &&
|
(features.noperspective_interpolation &&
|
||||||
ShouldDisableColorPerspective() != old_settings.gpu_pgxp_color_correction));
|
ShouldDisableColorPerspective() != old_settings.gpu_pgxp_color_correction) ||
|
||||||
|
m_allow_sprite_mode !=
|
||||||
|
ShouldAllowSpriteMode(m_resolution_scale, g_settings.gpu_texture_filter, g_settings.gpu_sprite_texture_filter));
|
||||||
|
|
||||||
if (m_resolution_scale != resolution_scale)
|
if (m_resolution_scale != resolution_scale)
|
||||||
{
|
{
|
||||||
|
@ -376,13 +396,15 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
||||||
|
|
||||||
m_resolution_scale = resolution_scale;
|
m_resolution_scale = resolution_scale;
|
||||||
m_multisamples = multisamples;
|
m_multisamples = multisamples;
|
||||||
m_true_color = g_settings.gpu_true_color;
|
|
||||||
m_texture_filtering = g_settings.gpu_texture_filter;
|
m_texture_filtering = g_settings.gpu_texture_filter;
|
||||||
|
m_sprite_texture_filtering = g_settings.gpu_sprite_texture_filter;
|
||||||
m_line_detect_mode = (m_resolution_scale > 1) ? g_settings.gpu_line_detect_mode : GPULineDetectMode::Disabled;
|
m_line_detect_mode = (m_resolution_scale > 1) ? g_settings.gpu_line_detect_mode : GPULineDetectMode::Disabled;
|
||||||
m_clamp_uvs = clamp_uvs;
|
|
||||||
m_compute_uv_range = m_clamp_uvs;
|
|
||||||
m_downsample_mode = GetDownsampleMode(resolution_scale);
|
m_downsample_mode = GetDownsampleMode(resolution_scale);
|
||||||
m_wireframe_mode = g_settings.gpu_wireframe_mode;
|
m_wireframe_mode = g_settings.gpu_wireframe_mode;
|
||||||
|
m_true_color = g_settings.gpu_true_color;
|
||||||
|
m_clamp_uvs = clamp_uvs;
|
||||||
|
m_compute_uv_range = m_clamp_uvs;
|
||||||
|
m_allow_sprite_mode = ShouldAllowSpriteMode(resolution_scale, m_texture_filtering, m_sprite_texture_filtering);
|
||||||
|
|
||||||
CheckSettings();
|
CheckSettings();
|
||||||
|
|
||||||
|
@ -454,13 +476,17 @@ void GPU_HW::CheckSettings()
|
||||||
TRANSLATE_STR("GPU_HW", "SSAA is not supported, using MSAA instead."),
|
TRANSLATE_STR("GPU_HW", "SSAA is not supported, using MSAA instead."),
|
||||||
Host::OSD_ERROR_DURATION);
|
Host::OSD_ERROR_DURATION);
|
||||||
}
|
}
|
||||||
if (!features.dual_source_blend && !features.framebuffer_fetch && IsBlendedTextureFiltering(m_texture_filtering))
|
if (!features.dual_source_blend && !features.framebuffer_fetch &&
|
||||||
|
(IsBlendedTextureFiltering(m_texture_filtering) || IsBlendedTextureFiltering(m_sprite_texture_filtering)))
|
||||||
{
|
{
|
||||||
Host::AddIconOSDMessage(
|
Host::AddIconOSDMessage(
|
||||||
"TextureFilterUnsupported", ICON_FA_EXCLAMATION_TRIANGLE,
|
"TextureFilterUnsupported", ICON_FA_EXCLAMATION_TRIANGLE,
|
||||||
fmt::format(TRANSLATE_FS("GPU_HW", "Texture filter '{}' is not supported with the current renderer."),
|
fmt::format(TRANSLATE_FS("GPU_HW", "Texture filter '{}/{}' is not supported with the current renderer."),
|
||||||
Settings::GetTextureFilterDisplayName(m_texture_filtering), Host::OSD_ERROR_DURATION));
|
Settings::GetTextureFilterDisplayName(m_texture_filtering),
|
||||||
|
Settings::GetTextureFilterName(m_sprite_texture_filtering), Host::OSD_ERROR_DURATION));
|
||||||
m_texture_filtering = GPUTextureFilter::Nearest;
|
m_texture_filtering = GPUTextureFilter::Nearest;
|
||||||
|
m_sprite_texture_filtering = GPUTextureFilter::Nearest;
|
||||||
|
m_allow_sprite_mode = ShouldAllowSpriteMode(m_resolution_scale, m_texture_filtering, m_sprite_texture_filtering);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!features.noperspective_interpolation && !ShouldDisableColorPerspective())
|
if (!features.noperspective_interpolation && !ShouldDisableColorPerspective())
|
||||||
|
@ -650,7 +676,8 @@ void GPU_HW::PrintSettingsToLog()
|
||||||
((m_true_color && g_settings.gpu_debanding) ? " (Debanding)" : ""));
|
((m_true_color && g_settings.gpu_debanding) ? " (Debanding)" : ""));
|
||||||
INFO_LOG("Force round texture coordinates: {}",
|
INFO_LOG("Force round texture coordinates: {}",
|
||||||
(m_resolution_scale > 1 && g_settings.gpu_force_round_texcoords) ? "Enabled" : "Disabled");
|
(m_resolution_scale > 1 && g_settings.gpu_force_round_texcoords) ? "Enabled" : "Disabled");
|
||||||
INFO_LOG("Texture Filtering: {}", Settings::GetTextureFilterDisplayName(m_texture_filtering));
|
INFO_LOG("Texture Filtering: {}/{}", Settings::GetTextureFilterDisplayName(m_texture_filtering),
|
||||||
|
Settings::GetTextureFilterDisplayName(m_sprite_texture_filtering));
|
||||||
INFO_LOG("Dual-source blending: {}", m_supports_dual_source_blend ? "Supported" : "Not supported");
|
INFO_LOG("Dual-source blending: {}", m_supports_dual_source_blend ? "Supported" : "Not supported");
|
||||||
INFO_LOG("Clamping UVs: {}", m_clamp_uvs ? "YES" : "NO");
|
INFO_LOG("Clamping UVs: {}", m_clamp_uvs ? "YES" : "NO");
|
||||||
INFO_LOG("Depth buffer: {}", m_pgxp_depth_buffer ? "YES" : "NO");
|
INFO_LOG("Depth buffer: {}", m_pgxp_depth_buffer ? "YES" : "NO");
|
||||||
|
@ -658,6 +685,7 @@ void GPU_HW::PrintSettingsToLog()
|
||||||
INFO_LOG("Wireframe rendering: {}", Settings::GetGPUWireframeModeDisplayName(m_wireframe_mode));
|
INFO_LOG("Wireframe rendering: {}", Settings::GetGPUWireframeModeDisplayName(m_wireframe_mode));
|
||||||
INFO_LOG("Line detection: {}", Settings::GetLineDetectModeDisplayName(m_line_detect_mode));
|
INFO_LOG("Line detection: {}", Settings::GetLineDetectModeDisplayName(m_line_detect_mode));
|
||||||
INFO_LOG("Using software renderer for readbacks: {}", m_sw_renderer ? "YES" : "NO");
|
INFO_LOG("Using software renderer for readbacks: {}", m_sw_renderer ? "YES" : "NO");
|
||||||
|
INFO_LOG("Separate sprite shaders: {}", m_allow_sprite_mode ? "YES" : "NO");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_HW::NeedsDepthBuffer() const
|
bool GPU_HW::NeedsDepthBuffer() const
|
||||||
|
@ -776,19 +804,23 @@ bool GPU_HW::CompilePipelines()
|
||||||
{
|
{
|
||||||
const GPUDevice::Features features = g_gpu_device->GetFeatures();
|
const GPUDevice::Features features = g_gpu_device->GetFeatures();
|
||||||
const bool per_sample_shading = g_settings.gpu_per_sample_shading && features.per_sample_shading;
|
const bool per_sample_shading = g_settings.gpu_per_sample_shading && features.per_sample_shading;
|
||||||
const bool force_round_texcoords = (m_resolution_scale > 1 && g_settings.gpu_force_round_texcoords);
|
const bool force_round_texcoords = (m_resolution_scale > 1 && m_texture_filtering == GPUTextureFilter::Nearest &&
|
||||||
|
g_settings.gpu_force_round_texcoords);
|
||||||
const bool needs_depth_buffer = NeedsDepthBuffer();
|
const bool needs_depth_buffer = NeedsDepthBuffer();
|
||||||
const bool write_mask_as_depth = (!m_pgxp_depth_buffer && needs_depth_buffer);
|
const bool write_mask_as_depth = (!m_pgxp_depth_buffer && needs_depth_buffer);
|
||||||
m_allow_shader_blend = (features.feedback_loops && (m_pgxp_depth_buffer || !needs_depth_buffer));
|
m_allow_shader_blend = (features.feedback_loops && (m_pgxp_depth_buffer || !needs_depth_buffer));
|
||||||
|
|
||||||
GPU_HW_ShaderGen shadergen(g_gpu_device->GetRenderAPI(), m_resolution_scale, m_multisamples, per_sample_shading,
|
GPU_HW_ShaderGen shadergen(g_gpu_device->GetRenderAPI(), m_resolution_scale, m_multisamples, per_sample_shading,
|
||||||
m_true_color, (m_resolution_scale > 1 && g_settings.gpu_scaled_dithering), m_clamp_uvs,
|
m_true_color, (m_resolution_scale > 1 && g_settings.gpu_scaled_dithering),
|
||||||
write_mask_as_depth, ShouldDisableColorPerspective(), m_supports_dual_source_blend,
|
write_mask_as_depth, ShouldDisableColorPerspective(), m_supports_dual_source_blend,
|
||||||
m_supports_framebuffer_fetch, g_settings.gpu_true_color && g_settings.gpu_debanding);
|
m_supports_framebuffer_fetch, g_settings.gpu_true_color && g_settings.gpu_debanding);
|
||||||
|
|
||||||
constexpr u32 active_texture_modes = 4;
|
const u32 active_texture_modes =
|
||||||
|
m_allow_sprite_mode ? NUM_TEXTURE_MODES :
|
||||||
|
(NUM_TEXTURE_MODES - (NUM_TEXTURE_MODES - static_cast<u32>(BatchTextureMode::SpriteStart)));
|
||||||
|
const u32 active_vertex_shaders = m_allow_sprite_mode ? 3 : 2;
|
||||||
const u32 total_pipelines =
|
const u32 total_pipelines =
|
||||||
2 + // vertex shaders
|
active_vertex_shaders + // vertex shaders
|
||||||
(active_texture_modes * 5 * 9 * 2 * 2 * 2) + // fragment shaders
|
(active_texture_modes * 5 * 9 * 2 * 2 * 2) + // fragment shaders
|
||||||
((m_pgxp_depth_buffer ? 2 : 1) * 5 * 5 * active_texture_modes * 2 * 2 * 2) + // batch pipelines
|
((m_pgxp_depth_buffer ? 2 : 1) * 5 * 5 * active_texture_modes * 2 * 2 * 2) + // batch pipelines
|
||||||
((m_wireframe_mode != GPUWireframeMode::Disabled) ? 1 : 0) + // wireframe
|
((m_wireframe_mode != GPUWireframeMode::Disabled) ? 1 : 0) + // wireframe
|
||||||
|
@ -804,19 +836,22 @@ bool GPU_HW::CompilePipelines()
|
||||||
|
|
||||||
ShaderCompileProgressTracker progress("Compiling Pipelines", total_pipelines);
|
ShaderCompileProgressTracker progress("Compiling Pipelines", total_pipelines);
|
||||||
|
|
||||||
// vertex shaders - [textured]
|
// vertex shaders - [non-textured/textured/sprite]
|
||||||
// fragment shaders - [render_mode][transparency_mode][texture_mode][check_mask][dithering][interlacing]
|
// fragment shaders - [render_mode][transparency_mode][texture_mode][check_mask][dithering][interlacing]
|
||||||
static constexpr auto destroy_shader = [](std::unique_ptr<GPUShader>& s) { s.reset(); };
|
static constexpr auto destroy_shader = [](std::unique_ptr<GPUShader>& s) { s.reset(); };
|
||||||
DimensionalArray<std::unique_ptr<GPUShader>, 2> batch_vertex_shaders{};
|
DimensionalArray<std::unique_ptr<GPUShader>, 3> batch_vertex_shaders{};
|
||||||
DimensionalArray<std::unique_ptr<GPUShader>, 2, 2, 2, NUM_TEXTURE_MODES, 5, 5> batch_fragment_shaders{};
|
DimensionalArray<std::unique_ptr<GPUShader>, 2, 2, 2, NUM_TEXTURE_MODES, 5, 5> batch_fragment_shaders{};
|
||||||
ScopedGuard batch_shader_guard([&batch_vertex_shaders, &batch_fragment_shaders]() {
|
ScopedGuard batch_shader_guard([&batch_vertex_shaders, &batch_fragment_shaders]() {
|
||||||
batch_vertex_shaders.enumerate(destroy_shader);
|
batch_vertex_shaders.enumerate(destroy_shader);
|
||||||
batch_fragment_shaders.enumerate(destroy_shader);
|
batch_fragment_shaders.enumerate(destroy_shader);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (u8 textured = 0; textured < 2; textured++)
|
for (u8 textured = 0; textured < active_vertex_shaders; textured++)
|
||||||
{
|
{
|
||||||
const std::string vs = shadergen.GenerateBatchVertexShader(ConvertToBoolUnchecked(textured), m_pgxp_depth_buffer);
|
const bool sprite = (textured > 1);
|
||||||
|
const bool uv_limits = ShouldClampUVs(sprite ? m_sprite_texture_filtering : m_texture_filtering);
|
||||||
|
const std::string vs = shadergen.GenerateBatchVertexShader(textured != 0, uv_limits,
|
||||||
|
!sprite && force_round_texcoords, m_pgxp_depth_buffer);
|
||||||
if (!(batch_vertex_shaders[textured] =
|
if (!(batch_vertex_shaders[textured] =
|
||||||
g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(), vs)))
|
g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(), vs)))
|
||||||
{
|
{
|
||||||
|
@ -858,11 +893,15 @@ bool GPU_HW::CompilePipelines()
|
||||||
{
|
{
|
||||||
for (u8 interlacing = 0; interlacing < 2; interlacing++)
|
for (u8 interlacing = 0; interlacing < 2; interlacing++)
|
||||||
{
|
{
|
||||||
|
const bool sprite = (static_cast<BatchTextureMode>(texture_mode) >= BatchTextureMode::SpriteStart);
|
||||||
|
const bool uv_limits = ShouldClampUVs(sprite ? m_sprite_texture_filtering : m_texture_filtering);
|
||||||
|
const BatchTextureMode shader_texmode = static_cast<BatchTextureMode>(
|
||||||
|
texture_mode - (sprite ? static_cast<u8>(BatchTextureMode::SpriteStart) : 0));
|
||||||
const std::string fs = shadergen.GenerateBatchFragmentShader(
|
const std::string fs = shadergen.GenerateBatchFragmentShader(
|
||||||
static_cast<BatchRenderMode>(render_mode), static_cast<GPUTransparencyMode>(transparency_mode),
|
static_cast<BatchRenderMode>(render_mode), static_cast<GPUTransparencyMode>(transparency_mode),
|
||||||
static_cast<BatchTextureMode>(texture_mode), m_texture_filtering, force_round_texcoords,
|
shader_texmode, sprite ? m_sprite_texture_filtering : m_texture_filtering, uv_limits,
|
||||||
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing),
|
!sprite && force_round_texcoords, ConvertToBoolUnchecked(dithering),
|
||||||
ConvertToBoolUnchecked(check_mask));
|
ConvertToBoolUnchecked(interlacing), ConvertToBoolUnchecked(check_mask));
|
||||||
|
|
||||||
if (!(batch_fragment_shaders[render_mode][transparency_mode][texture_mode][check_mask][dithering]
|
if (!(batch_fragment_shaders[render_mode][transparency_mode][texture_mode][check_mask][dithering]
|
||||||
[interlacing] = g_gpu_device->CreateShader(GPUShaderStage::Fragment,
|
[interlacing] = g_gpu_device->CreateShader(GPUShaderStage::Fragment,
|
||||||
|
@ -940,6 +979,8 @@ bool GPU_HW::CompilePipelines()
|
||||||
for (u8 check_mask = 0; check_mask < 2; check_mask++)
|
for (u8 check_mask = 0; check_mask < 2; check_mask++)
|
||||||
{
|
{
|
||||||
const bool textured = (static_cast<BatchTextureMode>(texture_mode) != BatchTextureMode::Disabled);
|
const bool textured = (static_cast<BatchTextureMode>(texture_mode) != BatchTextureMode::Disabled);
|
||||||
|
const bool sprite = (static_cast<BatchTextureMode>(texture_mode) >= BatchTextureMode::SpriteStart);
|
||||||
|
const bool uv_limits = ShouldClampUVs(sprite ? m_sprite_texture_filtering : m_texture_filtering);
|
||||||
const bool use_shader_blending =
|
const bool use_shader_blending =
|
||||||
(render_mode == static_cast<u8>(BatchRenderMode::ShaderBlend) &&
|
(render_mode == static_cast<u8>(BatchRenderMode::ShaderBlend) &&
|
||||||
((textured &&
|
((textured &&
|
||||||
|
@ -948,13 +989,13 @@ bool GPU_HW::CompilePipelines()
|
||||||
|
|
||||||
plconfig.input_layout.vertex_attributes =
|
plconfig.input_layout.vertex_attributes =
|
||||||
textured ?
|
textured ?
|
||||||
(m_clamp_uvs ? std::span<const GPUPipeline::VertexAttribute>(
|
(uv_limits ? std::span<const GPUPipeline::VertexAttribute>(
|
||||||
vertex_attributes, NUM_BATCH_TEXTURED_LIMITS_VERTEX_ATTRIBUTES) :
|
vertex_attributes, NUM_BATCH_TEXTURED_LIMITS_VERTEX_ATTRIBUTES) :
|
||||||
std::span<const GPUPipeline::VertexAttribute>(
|
std::span<const GPUPipeline::VertexAttribute>(vertex_attributes,
|
||||||
vertex_attributes, NUM_BATCH_TEXTURED_VERTEX_ATTRIBUTES)) :
|
NUM_BATCH_TEXTURED_VERTEX_ATTRIBUTES)) :
|
||||||
std::span<const GPUPipeline::VertexAttribute>(vertex_attributes, NUM_BATCH_VERTEX_ATTRIBUTES);
|
std::span<const GPUPipeline::VertexAttribute>(vertex_attributes, NUM_BATCH_VERTEX_ATTRIBUTES);
|
||||||
|
|
||||||
plconfig.vertex_shader = batch_vertex_shaders[BoolToUInt8(textured)].get();
|
plconfig.vertex_shader = batch_vertex_shaders[BoolToUInt8(textured) + BoolToUInt8(sprite)].get();
|
||||||
plconfig.fragment_shader =
|
plconfig.fragment_shader =
|
||||||
batch_fragment_shaders[render_mode]
|
batch_fragment_shaders[render_mode]
|
||||||
[use_shader_blending ? transparency_mode :
|
[use_shader_blending ? transparency_mode :
|
||||||
|
@ -982,7 +1023,8 @@ bool GPU_HW::CompilePipelines()
|
||||||
((static_cast<GPUTransparencyMode>(transparency_mode) != GPUTransparencyMode::Disabled &&
|
((static_cast<GPUTransparencyMode>(transparency_mode) != GPUTransparencyMode::Disabled &&
|
||||||
(static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::TransparencyDisabled &&
|
(static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::TransparencyDisabled &&
|
||||||
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque)) ||
|
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque)) ||
|
||||||
(textured && IsBlendedTextureFiltering(m_texture_filtering))))
|
(textured &&
|
||||||
|
IsBlendedTextureFiltering(sprite ? m_sprite_texture_filtering : m_texture_filtering))))
|
||||||
{
|
{
|
||||||
plconfig.blend.enable = true;
|
plconfig.blend.enable = true;
|
||||||
plconfig.blend.src_alpha_blend = GPUPipeline::BlendFunc::One;
|
plconfig.blend.src_alpha_blend = GPUPipeline::BlendFunc::One;
|
||||||
|
@ -1512,12 +1554,15 @@ ALWAYS_INLINE_RELEASE void GPU_HW::DrawBatchVertices(BatchRenderMode render_mode
|
||||||
u32 base_vertex)
|
u32 base_vertex)
|
||||||
{
|
{
|
||||||
// [depth_test][transparency_mode][render_mode][texture_mode][dithering][interlacing][check_mask]
|
// [depth_test][transparency_mode][render_mode][texture_mode][dithering][interlacing][check_mask]
|
||||||
|
const u8 texture_mode = static_cast<u8>(m_batch.texture_mode) +
|
||||||
|
((m_batch.texture_mode != BatchTextureMode::Disabled && m_batch.sprite_mode) ?
|
||||||
|
static_cast<u8>(BatchTextureMode::SpriteStart) :
|
||||||
|
0);
|
||||||
const u8 depth_test = BoolToUInt8(m_batch.use_depth_buffer);
|
const u8 depth_test = BoolToUInt8(m_batch.use_depth_buffer);
|
||||||
const u8 check_mask = BoolToUInt8(m_batch.check_mask_before_draw);
|
const u8 check_mask = BoolToUInt8(m_batch.check_mask_before_draw);
|
||||||
g_gpu_device->SetPipeline(m_batch_pipelines[depth_test][static_cast<u8>(m_batch.transparency_mode)][static_cast<u8>(
|
g_gpu_device->SetPipeline(m_batch_pipelines[depth_test][static_cast<u8>(m_batch.transparency_mode)][static_cast<u8>(
|
||||||
render_mode)][static_cast<u8>(m_batch.texture_mode)][BoolToUInt8(m_batch.dithering)]
|
render_mode)][texture_mode][BoolToUInt8(m_batch.dithering)][BoolToUInt8(m_batch.interlacing)][check_mask]
|
||||||
[BoolToUInt8(m_batch.interlacing)][check_mask]
|
.get());
|
||||||
.get());
|
|
||||||
|
|
||||||
if (render_mode != BatchRenderMode::ShaderBlend || m_supports_framebuffer_fetch)
|
if (render_mode != BatchRenderMode::ShaderBlend || m_supports_framebuffer_fetch)
|
||||||
g_gpu_device->DrawIndexed(num_indices, base_index, base_vertex);
|
g_gpu_device->DrawIndexed(num_indices, base_index, base_vertex);
|
||||||
|
@ -1628,6 +1673,36 @@ ALWAYS_INLINE_RELEASE void GPU_HW::HandleFlippedQuadTextureCoordinates(BatchVert
|
||||||
vertices[2].v++;
|
vertices[2].v++;
|
||||||
vertices[3].v++;
|
vertices[3].v++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2D polygons should have zero change in V on the X axis, and vice versa.
|
||||||
|
if (m_allow_sprite_mode)
|
||||||
|
SetBatchSpriteMode(zero_dudy && zero_dvdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPU_HW::IsPossibleSpritePolygon(const BatchVertex* vertices) const
|
||||||
|
{
|
||||||
|
const float abx = vertices[1].x - vertices[0].x;
|
||||||
|
const float aby = vertices[1].y - vertices[0].y;
|
||||||
|
const float bcx = vertices[2].x - vertices[1].x;
|
||||||
|
const float bcy = vertices[2].y - vertices[1].y;
|
||||||
|
const float cax = vertices[0].x - vertices[2].x;
|
||||||
|
const float cay = vertices[0].y - vertices[2].y;
|
||||||
|
const float dvdx = -aby * static_cast<float>(vertices[2].v) - bcy * static_cast<float>(vertices[0].v) -
|
||||||
|
cay * static_cast<float>(vertices[1].v);
|
||||||
|
const float dudy = +abx * static_cast<float>(vertices[2].u) + bcx * static_cast<float>(vertices[0].u) +
|
||||||
|
cax * static_cast<float>(vertices[1].u);
|
||||||
|
const float area = bcx * cay - bcy * cax;
|
||||||
|
const s32 texArea = (vertices[1].u - vertices[0].u) * (vertices[2].v - vertices[0].v) -
|
||||||
|
(vertices[2].u - vertices[0].u) * (vertices[1].v - vertices[0].v);
|
||||||
|
|
||||||
|
// Doesn't matter.
|
||||||
|
if (area == 0.0f || texArea == 0)
|
||||||
|
return m_batch.sprite_mode;
|
||||||
|
|
||||||
|
const float rcp_area = 1.0f / area;
|
||||||
|
const bool zero_dudy = ((dudy * rcp_area) == 0.0f);
|
||||||
|
const bool zero_dvdx = ((dvdx * rcp_area) == 0.0f);
|
||||||
|
return (zero_dudy && zero_dvdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE_RELEASE void GPU_HW::ExpandLineTriangles(BatchVertex* vertices, u32 base_vertex)
|
ALWAYS_INLINE_RELEASE void GPU_HW::ExpandLineTriangles(BatchVertex* vertices, u32 base_vertex)
|
||||||
|
@ -1837,6 +1912,22 @@ void GPU_HW::CheckForDepthClear(const BatchVertex* vertices, u32 num_vertices)
|
||||||
m_last_depth_z = average_z;
|
m_last_depth_z = average_z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPU_HW::SetBatchSpriteMode(bool enabled)
|
||||||
|
{
|
||||||
|
if (m_batch.sprite_mode == enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_batch_index_count > 0)
|
||||||
|
{
|
||||||
|
FlushRender();
|
||||||
|
EnsureVertexBufferSpaceForCurrentCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
GL_INS_FMT("Sprite mode is now {}", enabled ? "ON" : "OFF");
|
||||||
|
|
||||||
|
m_batch.sprite_mode = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
void GPU_HW::DrawLine(float x0, float y0, u32 col0, float x1, float y1, u32 col1, float depth)
|
void GPU_HW::DrawLine(float x0, float y0, u32 col0, float x1, float y1, u32 col1, float depth)
|
||||||
{
|
{
|
||||||
DebugAssert(m_batch_vertex_space >= 4 && m_batch_index_space >= 6);
|
DebugAssert(m_batch_vertex_space >= 4 && m_batch_index_space >= 6);
|
||||||
|
@ -1997,6 +2088,8 @@ void GPU_HW::LoadVertices()
|
||||||
const bool is_3d = (vertices[0].w != vertices[1].w || vertices[0].w != vertices[2].w);
|
const bool is_3d = (vertices[0].w != vertices[1].w || vertices[0].w != vertices[2].w);
|
||||||
if (m_resolution_scale > 1 && !is_3d && rc.quad_polygon)
|
if (m_resolution_scale > 1 && !is_3d && rc.quad_polygon)
|
||||||
HandleFlippedQuadTextureCoordinates(vertices.data());
|
HandleFlippedQuadTextureCoordinates(vertices.data());
|
||||||
|
else if (m_allow_sprite_mode)
|
||||||
|
SetBatchSpriteMode((pgxp && !is_3d) || IsPossibleSpritePolygon(vertices.data()));
|
||||||
|
|
||||||
if (m_compute_uv_range && textured)
|
if (m_compute_uv_range && textured)
|
||||||
ComputePolygonUVLimits(texpage, vertices.data(), num_vertices);
|
ComputePolygonUVLimits(texpage, vertices.data(), num_vertices);
|
||||||
|
@ -2160,6 +2253,7 @@ void GPU_HW::LoadVertices()
|
||||||
|
|
||||||
// we can split the rectangle up into potentially 8 quads
|
// we can split the rectangle up into potentially 8 quads
|
||||||
SetBatchDepthBuffer(false);
|
SetBatchDepthBuffer(false);
|
||||||
|
SetBatchSpriteMode(m_allow_sprite_mode);
|
||||||
DebugAssert(m_batch_vertex_space >= MAX_VERTICES_FOR_RECTANGLE &&
|
DebugAssert(m_batch_vertex_space >= MAX_VERTICES_FOR_RECTANGLE &&
|
||||||
m_batch_index_space >= MAX_VERTICES_FOR_RECTANGLE);
|
m_batch_index_space >= MAX_VERTICES_FOR_RECTANGLE);
|
||||||
|
|
||||||
|
@ -2499,7 +2593,8 @@ ALWAYS_INLINE_RELEASE bool GPU_HW::NeedsShaderBlending(GPUTransparencyMode trans
|
||||||
((check_mask && (m_pgxp_depth_buffer || !m_vram_depth_texture)) ||
|
((check_mask && (m_pgxp_depth_buffer || !m_vram_depth_texture)) ||
|
||||||
transparency == GPUTransparencyMode::BackgroundMinusForeground ||
|
transparency == GPUTransparencyMode::BackgroundMinusForeground ||
|
||||||
(!m_supports_dual_source_blend &&
|
(!m_supports_dual_source_blend &&
|
||||||
(transparency != GPUTransparencyMode::Disabled || IsBlendedTextureFiltering(m_texture_filtering)))));
|
(transparency != GPUTransparencyMode::Disabled || IsBlendedTextureFiltering(m_texture_filtering) ||
|
||||||
|
IsBlendedTextureFiltering(m_sprite_texture_filtering)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW::EnsureVertexBufferSpace(u32 required_vertices, u32 required_indices)
|
void GPU_HW::EnsureVertexBufferSpace(u32 required_vertices, u32 required_indices)
|
||||||
|
|
|
@ -40,7 +40,13 @@ public:
|
||||||
Direct16Bit,
|
Direct16Bit,
|
||||||
Disabled,
|
Disabled,
|
||||||
|
|
||||||
|
SpritePalette4Bit,
|
||||||
|
SpritePalette8Bit,
|
||||||
|
SpriteDirect16Bit,
|
||||||
|
|
||||||
MaxCount,
|
MaxCount,
|
||||||
|
|
||||||
|
SpriteStart = SpritePalette4Bit,
|
||||||
};
|
};
|
||||||
static_assert(static_cast<u8>(BatchTextureMode::Palette4Bit) == static_cast<u8>(GPUTextureMode::Palette4Bit) &&
|
static_assert(static_cast<u8>(BatchTextureMode::Palette4Bit) == static_cast<u8>(GPUTextureMode::Palette4Bit) &&
|
||||||
static_cast<u8>(BatchTextureMode::Palette8Bit) == static_cast<u8>(GPUTextureMode::Palette8Bit) &&
|
static_cast<u8>(BatchTextureMode::Palette8Bit) == static_cast<u8>(GPUTextureMode::Palette8Bit) &&
|
||||||
|
@ -108,6 +114,7 @@ private:
|
||||||
bool set_mask_while_drawing = false;
|
bool set_mask_while_drawing = false;
|
||||||
bool check_mask_before_draw = false;
|
bool check_mask_before_draw = false;
|
||||||
bool use_depth_buffer = false;
|
bool use_depth_buffer = false;
|
||||||
|
bool sprite_mode = false;
|
||||||
|
|
||||||
// Returns the render mode for this batch.
|
// Returns the render mode for this batch.
|
||||||
BatchRenderMode GetRenderMode() const;
|
BatchRenderMode GetRenderMode() const;
|
||||||
|
@ -201,6 +208,7 @@ private:
|
||||||
|
|
||||||
/// Handles quads with flipped texture coordinate directions.
|
/// Handles quads with flipped texture coordinate directions.
|
||||||
void HandleFlippedQuadTextureCoordinates(BatchVertex* vertices);
|
void HandleFlippedQuadTextureCoordinates(BatchVertex* vertices);
|
||||||
|
bool IsPossibleSpritePolygon(const BatchVertex* vertices) const;
|
||||||
void ExpandLineTriangles(BatchVertex* vertices, u32 base_vertex);
|
void ExpandLineTriangles(BatchVertex* vertices, u32 base_vertex);
|
||||||
|
|
||||||
/// Computes polygon U/V boundaries.
|
/// Computes polygon U/V boundaries.
|
||||||
|
@ -209,6 +217,7 @@ private:
|
||||||
/// Sets the depth test flag for PGXP depth buffering.
|
/// Sets the depth test flag for PGXP depth buffering.
|
||||||
void SetBatchDepthBuffer(bool enabled);
|
void SetBatchDepthBuffer(bool enabled);
|
||||||
void CheckForDepthClear(const BatchVertex* vertices, u32 num_vertices);
|
void CheckForDepthClear(const BatchVertex* vertices, u32 num_vertices);
|
||||||
|
void SetBatchSpriteMode(bool enabled);
|
||||||
|
|
||||||
void UpdateDownsamplingLevels();
|
void UpdateDownsamplingLevels();
|
||||||
void DownsampleFramebuffer(GPUTexture* source, u32 left, u32 top, u32 width, u32 height);
|
void DownsampleFramebuffer(GPUTexture* source, u32 left, u32 top, u32 width, u32 height);
|
||||||
|
@ -242,6 +251,7 @@ private:
|
||||||
u8 m_multisamples = 1;
|
u8 m_multisamples = 1;
|
||||||
|
|
||||||
GPUTextureFilter m_texture_filtering = GPUTextureFilter::Nearest;
|
GPUTextureFilter m_texture_filtering = GPUTextureFilter::Nearest;
|
||||||
|
GPUTextureFilter m_sprite_texture_filtering = GPUTextureFilter::Nearest;
|
||||||
GPULineDetectMode m_line_detect_mode = GPULineDetectMode::Disabled;
|
GPULineDetectMode m_line_detect_mode = GPULineDetectMode::Disabled;
|
||||||
GPUDownsampleMode m_downsample_mode = GPUDownsampleMode::Disabled;
|
GPUDownsampleMode m_downsample_mode = GPUDownsampleMode::Disabled;
|
||||||
GPUWireframeMode m_wireframe_mode = GPUWireframeMode::Disabled;
|
GPUWireframeMode m_wireframe_mode = GPUWireframeMode::Disabled;
|
||||||
|
@ -252,6 +262,7 @@ private:
|
||||||
bool m_pgxp_depth_buffer : 1 = false;
|
bool m_pgxp_depth_buffer : 1 = false;
|
||||||
bool m_clamp_uvs : 1 = false;
|
bool m_clamp_uvs : 1 = false;
|
||||||
bool m_compute_uv_range : 1 = false;
|
bool m_compute_uv_range : 1 = false;
|
||||||
|
bool m_allow_sprite_mode : 1 = false;
|
||||||
bool m_allow_shader_blend : 1 = false;
|
bool m_allow_shader_blend : 1 = false;
|
||||||
|
|
||||||
u8 m_texpage_dirty = 0;
|
u8 m_texpage_dirty = 0;
|
||||||
|
|
|
@ -6,14 +6,13 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
GPU_HW_ShaderGen::GPU_HW_ShaderGen(RenderAPI render_api, u32 resolution_scale, u32 multisamples,
|
GPU_HW_ShaderGen::GPU_HW_ShaderGen(RenderAPI render_api, u32 resolution_scale, u32 multisamples,
|
||||||
bool per_sample_shading, bool true_color, bool scaled_dithering, bool uv_limits,
|
bool per_sample_shading, bool true_color, bool scaled_dithering,
|
||||||
bool write_mask_as_depth, bool disable_color_perspective,
|
bool write_mask_as_depth, bool disable_color_perspective,
|
||||||
bool supports_dual_source_blend, bool supports_framebuffer_fetch, bool debanding)
|
bool supports_dual_source_blend, bool supports_framebuffer_fetch, bool debanding)
|
||||||
: ShaderGen(render_api, GetShaderLanguageForAPI(render_api), supports_dual_source_blend, supports_framebuffer_fetch),
|
: ShaderGen(render_api, GetShaderLanguageForAPI(render_api), supports_dual_source_blend, supports_framebuffer_fetch),
|
||||||
m_resolution_scale(resolution_scale), m_multisamples(multisamples), m_per_sample_shading(per_sample_shading),
|
m_resolution_scale(resolution_scale), m_multisamples(multisamples), m_per_sample_shading(per_sample_shading),
|
||||||
m_true_color(true_color), m_scaled_dithering(scaled_dithering), m_uv_limits(uv_limits),
|
m_true_color(true_color), m_scaled_dithering(scaled_dithering), m_write_mask_as_depth(write_mask_as_depth),
|
||||||
m_write_mask_as_depth(write_mask_as_depth), m_disable_color_perspective(disable_color_perspective),
|
m_disable_color_perspective(disable_color_perspective), m_debanding(debanding)
|
||||||
m_debanding(debanding)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,12 +57,14 @@ void GPU_HW_ShaderGen::WriteBatchUniformBuffer(std::stringstream& ss)
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured, bool pgxp_depth)
|
std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured, bool uv_limits, bool force_round_texcoords,
|
||||||
|
bool pgxp_depth)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
WriteHeader(ss);
|
WriteHeader(ss);
|
||||||
DefineMacro(ss, "TEXTURED", textured);
|
DefineMacro(ss, "TEXTURED", textured);
|
||||||
DefineMacro(ss, "UV_LIMITS", m_uv_limits);
|
DefineMacro(ss, "UV_LIMITS", uv_limits);
|
||||||
|
DefineMacro(ss, "FORCE_ROUND_TEXCOORDS", force_round_texcoords);
|
||||||
DefineMacro(ss, "PGXP_DEPTH", pgxp_depth);
|
DefineMacro(ss, "PGXP_DEPTH", pgxp_depth);
|
||||||
|
|
||||||
WriteCommonFunctions(ss);
|
WriteCommonFunctions(ss);
|
||||||
|
@ -71,7 +72,7 @@ std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured, bool pgxp
|
||||||
|
|
||||||
if (textured)
|
if (textured)
|
||||||
{
|
{
|
||||||
if (m_uv_limits)
|
if (uv_limits)
|
||||||
{
|
{
|
||||||
DeclareVertexEntryPoint(
|
DeclareVertexEntryPoint(
|
||||||
ss, {"float4 a_pos", "float4 a_col0", "uint a_texcoord", "uint a_texpage", "float4 a_uv_limits"}, 1, 1,
|
ss, {"float4 a_pos", "float4 a_col0", "uint a_texcoord", "uint a_texpage", "float4 a_uv_limits"}, 1, 1,
|
||||||
|
@ -137,6 +138,11 @@ std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured, bool pgxp
|
||||||
|
|
||||||
#if UV_LIMITS
|
#if UV_LIMITS
|
||||||
v_uv_limits = a_uv_limits * float4(255.0, 255.0, 255.0, 255.0);
|
v_uv_limits = a_uv_limits * float4(255.0, 255.0, 255.0, 255.0);
|
||||||
|
#if FORCE_ROUND_TEXCOORDS
|
||||||
|
// Add 0.5 to the upper bounds when upscaling, to work around interpolation differences.
|
||||||
|
// Limited to force-round-texcoord hack, to avoid breaking other games.
|
||||||
|
v_uv_limits.zw += 0.5;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -630,9 +636,12 @@ void FilteredSampleFromVRAM(uint4 texpage, float2 coords, float4 uv_limits,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(
|
std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMode render_mode,
|
||||||
GPU_HW::BatchRenderMode render_mode, GPUTransparencyMode transparency, GPU_HW::BatchTextureMode texture_mode,
|
GPUTransparencyMode transparency,
|
||||||
GPUTextureFilter texture_filtering, bool force_round_texcoords, bool dithering, bool interlacing, bool check_mask)
|
GPU_HW::BatchTextureMode texture_mode,
|
||||||
|
GPUTextureFilter texture_filtering, bool uv_limits,
|
||||||
|
bool force_round_texcoords, bool dithering, bool interlacing,
|
||||||
|
bool check_mask)
|
||||||
{
|
{
|
||||||
// TODO: don't write depth for shader blend
|
// TODO: don't write depth for shader blend
|
||||||
DebugAssert(transparency == GPUTransparencyMode::Disabled || render_mode == GPU_HW::BatchRenderMode::ShaderBlend);
|
DebugAssert(transparency == GPUTransparencyMode::Disabled || render_mode == GPU_HW::BatchRenderMode::ShaderBlend);
|
||||||
|
@ -666,7 +675,7 @@ std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(
|
||||||
DefineMacro(ss, "INTERLACING", interlacing);
|
DefineMacro(ss, "INTERLACING", interlacing);
|
||||||
DefineMacro(ss, "TRUE_COLOR", m_true_color);
|
DefineMacro(ss, "TRUE_COLOR", m_true_color);
|
||||||
DefineMacro(ss, "TEXTURE_FILTERING", texture_filtering != GPUTextureFilter::Nearest);
|
DefineMacro(ss, "TEXTURE_FILTERING", texture_filtering != GPUTextureFilter::Nearest);
|
||||||
DefineMacro(ss, "UV_LIMITS", m_uv_limits);
|
DefineMacro(ss, "UV_LIMITS", uv_limits);
|
||||||
DefineMacro(ss, "USE_DUAL_SOURCE", use_dual_source);
|
DefineMacro(ss, "USE_DUAL_SOURCE", use_dual_source);
|
||||||
DefineMacro(ss, "WRITE_MASK_AS_DEPTH", m_write_mask_as_depth);
|
DefineMacro(ss, "WRITE_MASK_AS_DEPTH", m_write_mask_as_depth);
|
||||||
DefineMacro(ss, "FORCE_ROUND_TEXCOORDS", force_round_texcoords);
|
DefineMacro(ss, "FORCE_ROUND_TEXCOORDS", force_round_texcoords);
|
||||||
|
@ -796,7 +805,7 @@ float3 ApplyDebanding(float2 frag_coord)
|
||||||
if (texture_filtering != GPUTextureFilter::Nearest)
|
if (texture_filtering != GPUTextureFilter::Nearest)
|
||||||
WriteBatchTextureFilter(ss, texture_filtering);
|
WriteBatchTextureFilter(ss, texture_filtering);
|
||||||
|
|
||||||
if (m_uv_limits)
|
if (uv_limits)
|
||||||
{
|
{
|
||||||
DeclareFragmentEntryPoint(ss, 1, 1,
|
DeclareFragmentEntryPoint(ss, 1, 1,
|
||||||
{{"nointerpolation", "uint4 v_texpage"}, {"nointerpolation", "float4 v_uv_limits"}},
|
{{"nointerpolation", "uint4 v_texpage"}, {"nointerpolation", "float4 v_uv_limits"}},
|
||||||
|
|
|
@ -9,15 +9,14 @@ class GPU_HW_ShaderGen : public ShaderGen
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GPU_HW_ShaderGen(RenderAPI render_api, u32 resolution_scale, u32 multisamples, bool per_sample_shading,
|
GPU_HW_ShaderGen(RenderAPI render_api, u32 resolution_scale, u32 multisamples, bool per_sample_shading,
|
||||||
bool true_color, bool scaled_dithering, bool uv_limits, bool write_mask_as_depth,
|
bool true_color, bool scaled_dithering, bool write_mask_as_depth, bool disable_color_perspective,
|
||||||
bool disable_color_perspective, bool supports_dual_source_blend, bool supports_framebuffer_fetch,
|
bool supports_dual_source_blend, bool supports_framebuffer_fetch, bool debanding);
|
||||||
bool debanding);
|
|
||||||
~GPU_HW_ShaderGen();
|
~GPU_HW_ShaderGen();
|
||||||
|
|
||||||
std::string GenerateBatchVertexShader(bool textured, bool pgxp_depth);
|
std::string GenerateBatchVertexShader(bool textured, bool uv_limits, bool force_round_texcoords, bool pgxp_depth);
|
||||||
std::string GenerateBatchFragmentShader(GPU_HW::BatchRenderMode render_mode, GPUTransparencyMode transparency,
|
std::string GenerateBatchFragmentShader(GPU_HW::BatchRenderMode render_mode, GPUTransparencyMode transparency,
|
||||||
GPU_HW::BatchTextureMode texture_mode, GPUTextureFilter texture_filtering,
|
GPU_HW::BatchTextureMode texture_mode, GPUTextureFilter texture_filtering,
|
||||||
bool force_round_texcoords, bool dithering, bool interlacing,
|
bool uv_limits, bool force_round_texcoords, bool dithering, bool interlacing,
|
||||||
bool check_mask);
|
bool check_mask);
|
||||||
std::string GenerateWireframeGeometryShader();
|
std::string GenerateWireframeGeometryShader();
|
||||||
std::string GenerateWireframeFragmentShader();
|
std::string GenerateWireframeFragmentShader();
|
||||||
|
@ -48,7 +47,6 @@ private:
|
||||||
bool m_per_sample_shading;
|
bool m_per_sample_shading;
|
||||||
bool m_true_color;
|
bool m_true_color;
|
||||||
bool m_scaled_dithering;
|
bool m_scaled_dithering;
|
||||||
bool m_uv_limits;
|
|
||||||
bool m_write_mask_as_depth;
|
bool m_write_mask_as_depth;
|
||||||
bool m_disable_color_perspective;
|
bool m_disable_color_perspective;
|
||||||
bool m_debanding;
|
bool m_debanding;
|
||||||
|
|
|
@ -548,7 +548,17 @@ void ImGuiManager::DrawEnhancementsOverlay()
|
||||||
if (g_settings.gpu_force_ntsc_timings && System::GetRegion() == ConsoleRegion::PAL)
|
if (g_settings.gpu_force_ntsc_timings && System::GetRegion() == ConsoleRegion::PAL)
|
||||||
text.append(" PAL60");
|
text.append(" PAL60");
|
||||||
if (g_settings.gpu_texture_filter != GPUTextureFilter::Nearest)
|
if (g_settings.gpu_texture_filter != GPUTextureFilter::Nearest)
|
||||||
text.append_format(" {}", Settings::GetTextureFilterName(g_settings.gpu_texture_filter));
|
{
|
||||||
|
if (g_settings.gpu_sprite_texture_filter != g_settings.gpu_texture_filter)
|
||||||
|
{
|
||||||
|
text.append_format(" {}/{}", Settings::GetTextureFilterName(g_settings.gpu_texture_filter),
|
||||||
|
Settings::GetTextureFilterName(g_settings.gpu_sprite_texture_filter));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text.append_format(" {}", Settings::GetTextureFilterName(g_settings.gpu_texture_filter));
|
||||||
|
}
|
||||||
|
}
|
||||||
if (g_settings.gpu_widescreen_hack && g_settings.display_aspect_ratio != DisplayAspectRatio::Auto &&
|
if (g_settings.gpu_widescreen_hack && g_settings.display_aspect_ratio != DisplayAspectRatio::Auto &&
|
||||||
g_settings.display_aspect_ratio != DisplayAspectRatio::R4_3)
|
g_settings.display_aspect_ratio != DisplayAspectRatio::R4_3)
|
||||||
{
|
{
|
||||||
|
@ -1144,9 +1154,9 @@ void SaveStateSelectorUI::SaveCurrentSlot()
|
||||||
if (!System::SaveState(path.c_str(), &error, g_settings.create_save_state_backups))
|
if (!System::SaveState(path.c_str(), &error, g_settings.create_save_state_backups))
|
||||||
{
|
{
|
||||||
Host::AddIconOSDMessage("SaveState", ICON_FA_EXCLAMATION_TRIANGLE,
|
Host::AddIconOSDMessage("SaveState", ICON_FA_EXCLAMATION_TRIANGLE,
|
||||||
fmt::format(TRANSLATE_FS("OSDMessage", "Failed to save state to slot {0}:\n{1}"),
|
fmt::format(TRANSLATE_FS("OSDMessage", "Failed to save state to slot {0}:\n{1}"),
|
||||||
GetCurrentSlot(), error.GetDescription()),
|
GetCurrentSlot(), error.GetDescription()),
|
||||||
Host::OSD_ERROR_DURATION);
|
Host::OSD_ERROR_DURATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -202,6 +202,9 @@ void Settings::Load(SettingsInterface& si)
|
||||||
ParseTextureFilterName(
|
ParseTextureFilterName(
|
||||||
si.GetStringValue("GPU", "TextureFilter", GetTextureFilterName(DEFAULT_GPU_TEXTURE_FILTER)).c_str())
|
si.GetStringValue("GPU", "TextureFilter", GetTextureFilterName(DEFAULT_GPU_TEXTURE_FILTER)).c_str())
|
||||||
.value_or(DEFAULT_GPU_TEXTURE_FILTER);
|
.value_or(DEFAULT_GPU_TEXTURE_FILTER);
|
||||||
|
gpu_sprite_texture_filter =
|
||||||
|
ParseTextureFilterName(si.GetStringValue("GPU", "SpriteTextureFilter", GetTextureFilterName(gpu_texture_filter)).c_str())
|
||||||
|
.value_or(gpu_texture_filter);
|
||||||
gpu_line_detect_mode =
|
gpu_line_detect_mode =
|
||||||
ParseLineDetectModeName(
|
ParseLineDetectModeName(
|
||||||
si.GetStringValue("GPU", "LineDetectMode", GetLineDetectModeName(DEFAULT_GPU_LINE_DETECT_MODE)).c_str())
|
si.GetStringValue("GPU", "LineDetectMode", GetLineDetectModeName(DEFAULT_GPU_LINE_DETECT_MODE)).c_str())
|
||||||
|
@ -498,6 +501,9 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const
|
||||||
si.SetBoolValue("GPU", "ScaledDithering", gpu_scaled_dithering);
|
si.SetBoolValue("GPU", "ScaledDithering", gpu_scaled_dithering);
|
||||||
si.SetBoolValue("GPU", "ForceRoundTextureCoordinates", gpu_force_round_texcoords);
|
si.SetBoolValue("GPU", "ForceRoundTextureCoordinates", gpu_force_round_texcoords);
|
||||||
si.SetStringValue("GPU", "TextureFilter", GetTextureFilterName(gpu_texture_filter));
|
si.SetStringValue("GPU", "TextureFilter", GetTextureFilterName(gpu_texture_filter));
|
||||||
|
si.SetStringValue(
|
||||||
|
"GPU", "SpriteTextureFilter",
|
||||||
|
(gpu_sprite_texture_filter != gpu_texture_filter) ? GetTextureFilterName(gpu_sprite_texture_filter) : "");
|
||||||
si.SetStringValue("GPU", "LineDetectMode", GetLineDetectModeName(gpu_line_detect_mode));
|
si.SetStringValue("GPU", "LineDetectMode", GetLineDetectModeName(gpu_line_detect_mode));
|
||||||
si.SetStringValue("GPU", "DownsampleMode", GetDownsampleModeName(gpu_downsample_mode));
|
si.SetStringValue("GPU", "DownsampleMode", GetDownsampleModeName(gpu_downsample_mode));
|
||||||
si.SetUIntValue("GPU", "DownsampleScale", gpu_downsample_scale);
|
si.SetUIntValue("GPU", "DownsampleScale", gpu_downsample_scale);
|
||||||
|
@ -706,6 +712,7 @@ void Settings::FixIncompatibleSettings(bool display_osd_messages)
|
||||||
g_settings.gpu_scaled_dithering = false;
|
g_settings.gpu_scaled_dithering = false;
|
||||||
g_settings.gpu_force_round_texcoords = false;
|
g_settings.gpu_force_round_texcoords = false;
|
||||||
g_settings.gpu_texture_filter = GPUTextureFilter::Nearest;
|
g_settings.gpu_texture_filter = GPUTextureFilter::Nearest;
|
||||||
|
g_settings.gpu_sprite_texture_filter = GPUTextureFilter::Nearest;
|
||||||
g_settings.gpu_line_detect_mode = GPULineDetectMode::Disabled;
|
g_settings.gpu_line_detect_mode = GPULineDetectMode::Disabled;
|
||||||
g_settings.gpu_disable_interlacing = false;
|
g_settings.gpu_disable_interlacing = false;
|
||||||
g_settings.gpu_force_ntsc_timings = false;
|
g_settings.gpu_force_ntsc_timings = false;
|
||||||
|
|
|
@ -119,6 +119,7 @@ struct Settings
|
||||||
bool gpu_scaled_dithering : 1 = true;
|
bool gpu_scaled_dithering : 1 = true;
|
||||||
bool gpu_force_round_texcoords : 1 = false;
|
bool gpu_force_round_texcoords : 1 = false;
|
||||||
GPUTextureFilter gpu_texture_filter = DEFAULT_GPU_TEXTURE_FILTER;
|
GPUTextureFilter gpu_texture_filter = DEFAULT_GPU_TEXTURE_FILTER;
|
||||||
|
GPUTextureFilter gpu_sprite_texture_filter = DEFAULT_GPU_TEXTURE_FILTER;
|
||||||
GPULineDetectMode gpu_line_detect_mode = DEFAULT_GPU_LINE_DETECT_MODE;
|
GPULineDetectMode gpu_line_detect_mode = DEFAULT_GPU_LINE_DETECT_MODE;
|
||||||
GPUDownsampleMode gpu_downsample_mode = DEFAULT_GPU_DOWNSAMPLE_MODE;
|
GPUDownsampleMode gpu_downsample_mode = DEFAULT_GPU_DOWNSAMPLE_MODE;
|
||||||
u8 gpu_downsample_scale = 1;
|
u8 gpu_downsample_scale = 1;
|
||||||
|
|
|
@ -4017,6 +4017,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
||||||
g_settings.gpu_scaled_dithering != old_settings.gpu_scaled_dithering ||
|
g_settings.gpu_scaled_dithering != old_settings.gpu_scaled_dithering ||
|
||||||
g_settings.gpu_force_round_texcoords != old_settings.gpu_force_round_texcoords ||
|
g_settings.gpu_force_round_texcoords != old_settings.gpu_force_round_texcoords ||
|
||||||
g_settings.gpu_texture_filter != old_settings.gpu_texture_filter ||
|
g_settings.gpu_texture_filter != old_settings.gpu_texture_filter ||
|
||||||
|
g_settings.gpu_sprite_texture_filter != old_settings.gpu_sprite_texture_filter ||
|
||||||
g_settings.gpu_line_detect_mode != old_settings.gpu_line_detect_mode ||
|
g_settings.gpu_line_detect_mode != old_settings.gpu_line_detect_mode ||
|
||||||
g_settings.gpu_disable_interlacing != old_settings.gpu_disable_interlacing ||
|
g_settings.gpu_disable_interlacing != old_settings.gpu_disable_interlacing ||
|
||||||
g_settings.gpu_force_ntsc_timings != old_settings.gpu_force_ntsc_timings ||
|
g_settings.gpu_force_ntsc_timings != old_settings.gpu_force_ntsc_timings ||
|
||||||
|
|
|
@ -55,6 +55,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.textureFiltering, "GPU", "TextureFilter",
|
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.textureFiltering, "GPU", "TextureFilter",
|
||||||
&Settings::ParseTextureFilterName, &Settings::GetTextureFilterName,
|
&Settings::ParseTextureFilterName, &Settings::GetTextureFilterName,
|
||||||
Settings::DEFAULT_GPU_TEXTURE_FILTER);
|
Settings::DEFAULT_GPU_TEXTURE_FILTER);
|
||||||
|
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.spriteTextureFiltering, "GPU", "SpriteTextureFilter",
|
||||||
|
&Settings::ParseTextureFilterName, &Settings::GetTextureFilterName,
|
||||||
|
Settings::DEFAULT_GPU_TEXTURE_FILTER);
|
||||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.gpuDownsampleMode, "GPU", "DownsampleMode",
|
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.gpuDownsampleMode, "GPU", "DownsampleMode",
|
||||||
&Settings::ParseDownsampleModeName, &Settings::GetDownsampleModeName,
|
&Settings::ParseDownsampleModeName, &Settings::GetDownsampleModeName,
|
||||||
Settings::DEFAULT_GPU_DOWNSAMPLE_MODE);
|
Settings::DEFAULT_GPU_DOWNSAMPLE_MODE);
|
||||||
|
@ -526,6 +529,8 @@ void GraphicsSettingsWidget::setupAdditionalUi()
|
||||||
{
|
{
|
||||||
m_ui.textureFiltering->addItem(
|
m_ui.textureFiltering->addItem(
|
||||||
QString::fromUtf8(Settings::GetTextureFilterDisplayName(static_cast<GPUTextureFilter>(i))));
|
QString::fromUtf8(Settings::GetTextureFilterDisplayName(static_cast<GPUTextureFilter>(i))));
|
||||||
|
m_ui.spriteTextureFiltering->addItem(
|
||||||
|
QString::fromUtf8(Settings::GetTextureFilterDisplayName(static_cast<GPUTextureFilter>(i))));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < static_cast<u32>(GPUDownsampleMode::Count); i++)
|
for (u32 i = 0; i < static_cast<u32>(GPUDownsampleMode::Count); i++)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>584</width>
|
<width>584</width>
|
||||||
<height>430</height>
|
<height>450</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -216,17 +216,14 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="4" column="0">
|
||||||
<widget class="QComboBox" name="textureFiltering"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Aspect Ratio:</string>
|
<string>Aspect Ratio:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="4" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,0,0">
|
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,0,0">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="displayAspectRatio"/>
|
<widget class="QComboBox" name="displayAspectRatio"/>
|
||||||
|
@ -260,37 +257,37 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Deinterlacing:</string>
|
<string>Deinterlacing:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="5" column="1">
|
||||||
<widget class="QComboBox" name="displayDeinterlacing"/>
|
<widget class="QComboBox" name="displayDeinterlacing"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="6" column="0">
|
||||||
<widget class="QLabel" name="label_7">
|
<widget class="QLabel" name="label_7">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Crop:</string>
|
<string>Crop:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="QComboBox" name="displayCropMode"/>
|
<widget class="QComboBox" name="displayCropMode"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="7" column="0">
|
||||||
<widget class="QLabel" name="label_8">
|
<widget class="QLabel" name="label_8">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Scaling:</string>
|
<string>Scaling:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="7" column="1">
|
||||||
<widget class="QComboBox" name="displayScaling"/>
|
<widget class="QComboBox" name="displayScaling"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0" colspan="2">
|
<item row="8" column="0" colspan="2">
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QCheckBox" name="pgxpDepthBuffer">
|
<widget class="QCheckBox" name="pgxpDepthBuffer">
|
||||||
|
@ -350,6 +347,19 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QComboBox" name="textureFiltering"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>Sprite Texture Filtering:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QComboBox" name="spriteTextureFiltering"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>780</width>
|
<width>780</width>
|
||||||
<height>490</height>
|
<height>650</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
|
Loading…
Reference in a new issue