mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-20 07:15: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 (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,
|
||||
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_sprite_texture_filter = GPUTextureFilter::Nearest;
|
||||
}
|
||||
|
||||
if (HasTrait(Trait::DisableScaledDithering))
|
||||
|
|
|
@ -59,10 +59,17 @@ ALWAYS_INLINE_RELEASE static u32 GetBoxDownsampleScale(u32 resolution_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.
|
||||
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()
|
||||
|
@ -73,7 +80,16 @@ ALWAYS_INLINE static bool ShouldDisableColorPerspective()
|
|||
/// Returns true if the specified texture filtering mode requires dual-source blending.
|
||||
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.
|
||||
|
@ -193,17 +209,18 @@ bool GPU_HW::Initialize()
|
|||
|
||||
m_resolution_scale = Truncate8(CalculateResolutionScale());
|
||||
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_framebuffer_fetch = features.framebuffer_fetch;
|
||||
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_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();
|
||||
|
||||
|
@ -317,7 +334,7 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
|||
|
||||
const u8 resolution_scale = Truncate8(CalculateResolutionScale());
|
||||
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 =
|
||||
(m_resolution_scale != resolution_scale || m_multisamples != multisamples ||
|
||||
(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_texture_filter == GPUTextureFilter::Nearest &&
|
||||
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 ||
|
||||
(m_downsample_mode == GPUDownsampleMode::Box &&
|
||||
g_settings.gpu_downsample_scale != old_settings.gpu_downsample_scale))) ||
|
||||
(features.geometry_shaders && g_settings.gpu_wireframe_mode != old_settings.gpu_wireframe_mode) ||
|
||||
m_pgxp_depth_buffer != g_settings.UsingPGXPDepthBuffer() ||
|
||||
(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)
|
||||
{
|
||||
|
@ -376,13 +396,15 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
|||
|
||||
m_resolution_scale = resolution_scale;
|
||||
m_multisamples = multisamples;
|
||||
m_true_color = g_settings.gpu_true_color;
|
||||
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_clamp_uvs = clamp_uvs;
|
||||
m_compute_uv_range = m_clamp_uvs;
|
||||
m_downsample_mode = GetDownsampleMode(resolution_scale);
|
||||
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();
|
||||
|
||||
|
@ -454,13 +476,17 @@ void GPU_HW::CheckSettings()
|
|||
TRANSLATE_STR("GPU_HW", "SSAA is not supported, using MSAA instead."),
|
||||
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(
|
||||
"TextureFilterUnsupported", ICON_FA_EXCLAMATION_TRIANGLE,
|
||||
fmt::format(TRANSLATE_FS("GPU_HW", "Texture filter '{}' is not supported with the current renderer."),
|
||||
Settings::GetTextureFilterDisplayName(m_texture_filtering), Host::OSD_ERROR_DURATION));
|
||||
fmt::format(TRANSLATE_FS("GPU_HW", "Texture filter '{}/{}' is not supported with the current renderer."),
|
||||
Settings::GetTextureFilterDisplayName(m_texture_filtering),
|
||||
Settings::GetTextureFilterName(m_sprite_texture_filtering), Host::OSD_ERROR_DURATION));
|
||||
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())
|
||||
|
@ -650,7 +676,8 @@ void GPU_HW::PrintSettingsToLog()
|
|||
((m_true_color && g_settings.gpu_debanding) ? " (Debanding)" : ""));
|
||||
INFO_LOG("Force round texture coordinates: {}",
|
||||
(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("Clamping UVs: {}", m_clamp_uvs ? "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("Line detection: {}", Settings::GetLineDetectModeDisplayName(m_line_detect_mode));
|
||||
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
|
||||
|
@ -776,19 +804,23 @@ bool GPU_HW::CompilePipelines()
|
|||
{
|
||||
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 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 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));
|
||||
|
||||
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,
|
||||
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 =
|
||||
2 + // vertex shaders
|
||||
active_vertex_shaders + // vertex 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_wireframe_mode != GPUWireframeMode::Disabled) ? 1 : 0) + // wireframe
|
||||
|
@ -804,19 +836,22 @@ bool GPU_HW::CompilePipelines()
|
|||
|
||||
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]
|
||||
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{};
|
||||
ScopedGuard batch_shader_guard([&batch_vertex_shaders, &batch_fragment_shaders]() {
|
||||
batch_vertex_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] =
|
||||
g_gpu_device->CreateShader(GPUShaderStage::Vertex, shadergen.GetLanguage(), vs)))
|
||||
{
|
||||
|
@ -858,11 +893,15 @@ bool GPU_HW::CompilePipelines()
|
|||
{
|
||||
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(
|
||||
static_cast<BatchRenderMode>(render_mode), static_cast<GPUTransparencyMode>(transparency_mode),
|
||||
static_cast<BatchTextureMode>(texture_mode), m_texture_filtering, force_round_texcoords,
|
||||
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing),
|
||||
ConvertToBoolUnchecked(check_mask));
|
||||
shader_texmode, sprite ? m_sprite_texture_filtering : m_texture_filtering, uv_limits,
|
||||
!sprite && force_round_texcoords, ConvertToBoolUnchecked(dithering),
|
||||
ConvertToBoolUnchecked(interlacing), ConvertToBoolUnchecked(check_mask));
|
||||
|
||||
if (!(batch_fragment_shaders[render_mode][transparency_mode][texture_mode][check_mask][dithering]
|
||||
[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++)
|
||||
{
|
||||
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 =
|
||||
(render_mode == static_cast<u8>(BatchRenderMode::ShaderBlend) &&
|
||||
((textured &&
|
||||
|
@ -948,13 +989,13 @@ bool GPU_HW::CompilePipelines()
|
|||
|
||||
plconfig.input_layout.vertex_attributes =
|
||||
textured ?
|
||||
(m_clamp_uvs ? std::span<const GPUPipeline::VertexAttribute>(
|
||||
(uv_limits ? std::span<const GPUPipeline::VertexAttribute>(
|
||||
vertex_attributes, NUM_BATCH_TEXTURED_LIMITS_VERTEX_ATTRIBUTES) :
|
||||
std::span<const GPUPipeline::VertexAttribute>(
|
||||
vertex_attributes, NUM_BATCH_TEXTURED_VERTEX_ATTRIBUTES)) :
|
||||
std::span<const GPUPipeline::VertexAttribute>(vertex_attributes,
|
||||
NUM_BATCH_TEXTURED_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 =
|
||||
batch_fragment_shaders[render_mode]
|
||||
[use_shader_blending ? transparency_mode :
|
||||
|
@ -982,7 +1023,8 @@ bool GPU_HW::CompilePipelines()
|
|||
((static_cast<GPUTransparencyMode>(transparency_mode) != GPUTransparencyMode::Disabled &&
|
||||
(static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::TransparencyDisabled &&
|
||||
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.src_alpha_blend = GPUPipeline::BlendFunc::One;
|
||||
|
@ -1512,11 +1554,14 @@ ALWAYS_INLINE_RELEASE void GPU_HW::DrawBatchVertices(BatchRenderMode render_mode
|
|||
u32 base_vertex)
|
||||
{
|
||||
// [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 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>(
|
||||
render_mode)][static_cast<u8>(m_batch.texture_mode)][BoolToUInt8(m_batch.dithering)]
|
||||
[BoolToUInt8(m_batch.interlacing)][check_mask]
|
||||
render_mode)][texture_mode][BoolToUInt8(m_batch.dithering)][BoolToUInt8(m_batch.interlacing)][check_mask]
|
||||
.get());
|
||||
|
||||
if (render_mode != BatchRenderMode::ShaderBlend || m_supports_framebuffer_fetch)
|
||||
|
@ -1628,6 +1673,36 @@ ALWAYS_INLINE_RELEASE void GPU_HW::HandleFlippedQuadTextureCoordinates(BatchVert
|
|||
vertices[2].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)
|
||||
|
@ -1837,6 +1912,22 @@ void GPU_HW::CheckForDepthClear(const BatchVertex* vertices, u32 num_vertices)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
if (m_resolution_scale > 1 && !is_3d && rc.quad_polygon)
|
||||
HandleFlippedQuadTextureCoordinates(vertices.data());
|
||||
else if (m_allow_sprite_mode)
|
||||
SetBatchSpriteMode((pgxp && !is_3d) || IsPossibleSpritePolygon(vertices.data()));
|
||||
|
||||
if (m_compute_uv_range && textured)
|
||||
ComputePolygonUVLimits(texpage, vertices.data(), num_vertices);
|
||||
|
@ -2160,6 +2253,7 @@ void GPU_HW::LoadVertices()
|
|||
|
||||
// we can split the rectangle up into potentially 8 quads
|
||||
SetBatchDepthBuffer(false);
|
||||
SetBatchSpriteMode(m_allow_sprite_mode);
|
||||
DebugAssert(m_batch_vertex_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)) ||
|
||||
transparency == GPUTransparencyMode::BackgroundMinusForeground ||
|
||||
(!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)
|
||||
|
|
|
@ -40,7 +40,13 @@ public:
|
|||
Direct16Bit,
|
||||
Disabled,
|
||||
|
||||
SpritePalette4Bit,
|
||||
SpritePalette8Bit,
|
||||
SpriteDirect16Bit,
|
||||
|
||||
MaxCount,
|
||||
|
||||
SpriteStart = SpritePalette4Bit,
|
||||
};
|
||||
static_assert(static_cast<u8>(BatchTextureMode::Palette4Bit) == static_cast<u8>(GPUTextureMode::Palette4Bit) &&
|
||||
static_cast<u8>(BatchTextureMode::Palette8Bit) == static_cast<u8>(GPUTextureMode::Palette8Bit) &&
|
||||
|
@ -108,6 +114,7 @@ private:
|
|||
bool set_mask_while_drawing = false;
|
||||
bool check_mask_before_draw = false;
|
||||
bool use_depth_buffer = false;
|
||||
bool sprite_mode = false;
|
||||
|
||||
// Returns the render mode for this batch.
|
||||
BatchRenderMode GetRenderMode() const;
|
||||
|
@ -201,6 +208,7 @@ private:
|
|||
|
||||
/// Handles quads with flipped texture coordinate directions.
|
||||
void HandleFlippedQuadTextureCoordinates(BatchVertex* vertices);
|
||||
bool IsPossibleSpritePolygon(const BatchVertex* vertices) const;
|
||||
void ExpandLineTriangles(BatchVertex* vertices, u32 base_vertex);
|
||||
|
||||
/// Computes polygon U/V boundaries.
|
||||
|
@ -209,6 +217,7 @@ private:
|
|||
/// Sets the depth test flag for PGXP depth buffering.
|
||||
void SetBatchDepthBuffer(bool enabled);
|
||||
void CheckForDepthClear(const BatchVertex* vertices, u32 num_vertices);
|
||||
void SetBatchSpriteMode(bool enabled);
|
||||
|
||||
void UpdateDownsamplingLevels();
|
||||
void DownsampleFramebuffer(GPUTexture* source, u32 left, u32 top, u32 width, u32 height);
|
||||
|
@ -242,6 +251,7 @@ private:
|
|||
u8 m_multisamples = 1;
|
||||
|
||||
GPUTextureFilter m_texture_filtering = GPUTextureFilter::Nearest;
|
||||
GPUTextureFilter m_sprite_texture_filtering = GPUTextureFilter::Nearest;
|
||||
GPULineDetectMode m_line_detect_mode = GPULineDetectMode::Disabled;
|
||||
GPUDownsampleMode m_downsample_mode = GPUDownsampleMode::Disabled;
|
||||
GPUWireframeMode m_wireframe_mode = GPUWireframeMode::Disabled;
|
||||
|
@ -252,6 +262,7 @@ private:
|
|||
bool m_pgxp_depth_buffer : 1 = false;
|
||||
bool m_clamp_uvs : 1 = false;
|
||||
bool m_compute_uv_range : 1 = false;
|
||||
bool m_allow_sprite_mode : 1 = false;
|
||||
bool m_allow_shader_blend : 1 = false;
|
||||
|
||||
u8 m_texpage_dirty = 0;
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
#include <cstdio>
|
||||
|
||||
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 supports_dual_source_blend, bool supports_framebuffer_fetch, bool debanding)
|
||||
: 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_true_color(true_color), m_scaled_dithering(scaled_dithering), m_uv_limits(uv_limits),
|
||||
m_write_mask_as_depth(write_mask_as_depth), m_disable_color_perspective(disable_color_perspective),
|
||||
m_debanding(debanding)
|
||||
m_true_color(true_color), m_scaled_dithering(scaled_dithering), m_write_mask_as_depth(write_mask_as_depth),
|
||||
m_disable_color_perspective(disable_color_perspective), m_debanding(debanding)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -58,12 +57,14 @@ void GPU_HW_ShaderGen::WriteBatchUniformBuffer(std::stringstream& ss)
|
|||
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;
|
||||
WriteHeader(ss);
|
||||
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);
|
||||
|
||||
WriteCommonFunctions(ss);
|
||||
|
@ -71,7 +72,7 @@ std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured, bool pgxp
|
|||
|
||||
if (textured)
|
||||
{
|
||||
if (m_uv_limits)
|
||||
if (uv_limits)
|
||||
{
|
||||
DeclareVertexEntryPoint(
|
||||
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
|
||||
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
|
||||
}
|
||||
|
@ -630,9 +636,12 @@ void FilteredSampleFromVRAM(uint4 texpage, float2 coords, float4 uv_limits,
|
|||
}
|
||||
}
|
||||
|
||||
std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(
|
||||
GPU_HW::BatchRenderMode render_mode, GPUTransparencyMode transparency, GPU_HW::BatchTextureMode texture_mode,
|
||||
GPUTextureFilter texture_filtering, bool force_round_texcoords, bool dithering, bool interlacing, bool check_mask)
|
||||
std::string GPU_HW_ShaderGen::GenerateBatchFragmentShader(GPU_HW::BatchRenderMode render_mode,
|
||||
GPUTransparencyMode transparency,
|
||||
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
|
||||
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, "TRUE_COLOR", m_true_color);
|
||||
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, "WRITE_MASK_AS_DEPTH", m_write_mask_as_depth);
|
||||
DefineMacro(ss, "FORCE_ROUND_TEXCOORDS", force_round_texcoords);
|
||||
|
@ -796,7 +805,7 @@ float3 ApplyDebanding(float2 frag_coord)
|
|||
if (texture_filtering != GPUTextureFilter::Nearest)
|
||||
WriteBatchTextureFilter(ss, texture_filtering);
|
||||
|
||||
if (m_uv_limits)
|
||||
if (uv_limits)
|
||||
{
|
||||
DeclareFragmentEntryPoint(ss, 1, 1,
|
||||
{{"nointerpolation", "uint4 v_texpage"}, {"nointerpolation", "float4 v_uv_limits"}},
|
||||
|
|
|
@ -9,15 +9,14 @@ class GPU_HW_ShaderGen : public ShaderGen
|
|||
{
|
||||
public:
|
||||
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 disable_color_perspective, bool supports_dual_source_blend, bool supports_framebuffer_fetch,
|
||||
bool debanding);
|
||||
bool true_color, bool scaled_dithering, bool write_mask_as_depth, bool disable_color_perspective,
|
||||
bool supports_dual_source_blend, bool supports_framebuffer_fetch, bool debanding);
|
||||
~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,
|
||||
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);
|
||||
std::string GenerateWireframeGeometryShader();
|
||||
std::string GenerateWireframeFragmentShader();
|
||||
|
@ -48,7 +47,6 @@ private:
|
|||
bool m_per_sample_shading;
|
||||
bool m_true_color;
|
||||
bool m_scaled_dithering;
|
||||
bool m_uv_limits;
|
||||
bool m_write_mask_as_depth;
|
||||
bool m_disable_color_perspective;
|
||||
bool m_debanding;
|
||||
|
|
|
@ -548,7 +548,17 @@ void ImGuiManager::DrawEnhancementsOverlay()
|
|||
if (g_settings.gpu_force_ntsc_timings && System::GetRegion() == ConsoleRegion::PAL)
|
||||
text.append(" PAL60");
|
||||
if (g_settings.gpu_texture_filter != GPUTextureFilter::Nearest)
|
||||
{
|
||||
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 &&
|
||||
g_settings.display_aspect_ratio != DisplayAspectRatio::R4_3)
|
||||
{
|
||||
|
|
|
@ -202,6 +202,9 @@ void Settings::Load(SettingsInterface& si)
|
|||
ParseTextureFilterName(
|
||||
si.GetStringValue("GPU", "TextureFilter", GetTextureFilterName(DEFAULT_GPU_TEXTURE_FILTER)).c_str())
|
||||
.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 =
|
||||
ParseLineDetectModeName(
|
||||
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", "ForceRoundTextureCoordinates", gpu_force_round_texcoords);
|
||||
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", "DownsampleMode", GetDownsampleModeName(gpu_downsample_mode));
|
||||
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_force_round_texcoords = false;
|
||||
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_disable_interlacing = false;
|
||||
g_settings.gpu_force_ntsc_timings = false;
|
||||
|
|
|
@ -119,6 +119,7 @@ struct Settings
|
|||
bool gpu_scaled_dithering : 1 = true;
|
||||
bool gpu_force_round_texcoords : 1 = false;
|
||||
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;
|
||||
GPUDownsampleMode gpu_downsample_mode = DEFAULT_GPU_DOWNSAMPLE_MODE;
|
||||
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_force_round_texcoords != old_settings.gpu_force_round_texcoords ||
|
||||
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_disable_interlacing != old_settings.gpu_disable_interlacing ||
|
||||
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",
|
||||
&Settings::ParseTextureFilterName, &Settings::GetTextureFilterName,
|
||||
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",
|
||||
&Settings::ParseDownsampleModeName, &Settings::GetDownsampleModeName,
|
||||
Settings::DEFAULT_GPU_DOWNSAMPLE_MODE);
|
||||
|
@ -526,6 +529,8 @@ void GraphicsSettingsWidget::setupAdditionalUi()
|
|||
{
|
||||
m_ui.textureFiltering->addItem(
|
||||
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++)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>584</width>
|
||||
<height>430</height>
|
||||
<height>450</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -216,17 +216,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="textureFiltering"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Aspect Ratio:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,0,0">
|
||||
<item>
|
||||
<widget class="QComboBox" name="displayAspectRatio"/>
|
||||
|
@ -260,37 +257,37 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Deinterlacing:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="displayDeinterlacing"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Crop:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="displayCropMode"/>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Scaling:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QComboBox" name="displayScaling"/>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<item row="8" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="pgxpDepthBuffer">
|
||||
|
@ -350,6 +347,19 @@
|
|||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>780</width>
|
||||
<height>490</height>
|
||||
<height>650</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
Loading…
Reference in a new issue