mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-25 23:25:41 +00:00
GPU: Add wireframe rendering/overlay
This commit is contained in:
parent
e804b5e701
commit
7ad1b8d093
|
@ -2872,8 +2872,8 @@ void FullscreenUI::DrawBIOSSettingsPage()
|
|||
FSUI_CSTR("Patches the BIOS to skip the boot animation. Safe to enable."), "BIOS", "PatchFastBoot",
|
||||
Settings::DEFAULT_FAST_BOOT_VALUE);
|
||||
DrawToggleSetting(bsi, FSUI_CSTR("Enable TTY Logging"),
|
||||
FSUI_CSTR("Logs BIOS calls to printf(). Not all games contain debugging messages."),
|
||||
"BIOS", "TTYLogging", false);
|
||||
FSUI_CSTR("Logs BIOS calls to printf(). Not all games contain debugging messages."), "BIOS",
|
||||
"TTYLogging", false);
|
||||
|
||||
EndMenuButtons();
|
||||
}
|
||||
|
@ -4695,6 +4695,11 @@ void FullscreenUI::DrawAdvancedSettingsPage()
|
|||
bsi, FSUI_CSTR("Stretch Display Vertically"),
|
||||
FSUI_CSTR("Stretches the display to match the aspect ratio by multiplying vertically instead of horizontally."),
|
||||
"Display", "StretchVertically", false);
|
||||
DrawEnumSetting(bsi, FSUI_CSTR("Wireframe Rendering"),
|
||||
FSUI_CSTR("Overlays or replaces normal triangle drawing with a wireframe/line view."), "GPU",
|
||||
"WireframeMode", GPUWireframeMode::Disabled, &Settings::ParseGPUWireframeMode,
|
||||
&Settings::GetGPUWireframeModeName, &Settings::GetGPUWireframeModeDisplayName,
|
||||
GPUWireframeMode::Count);
|
||||
|
||||
MenuHeading(FSUI_CSTR("PGXP Settings"));
|
||||
|
||||
|
|
|
@ -45,6 +45,11 @@ ALWAYS_INLINE static constexpr std::tuple<T, T> MinMax(T v1, T v2)
|
|||
return std::tie(v1, v2);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE static u32 GetMaxResolutionScale()
|
||||
{
|
||||
return g_gpu_device->GetMaxTextureSize() / VRAM_WIDTH;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE static bool ShouldUseUVLimits()
|
||||
{
|
||||
// We only need UV limits if PGXP is enabled, or texture filtering is enabled.
|
||||
|
@ -57,7 +62,7 @@ ALWAYS_INLINE static bool ShouldDisableColorPerspective()
|
|||
}
|
||||
|
||||
/// Returns true if the specified texture filtering mode requires dual-source blending.
|
||||
static bool TextureFilterRequiresDualSourceBlend(GPUTextureFilter filter)
|
||||
ALWAYS_INLINE static bool TextureFilterRequiresDualSourceBlend(GPUTextureFilter filter)
|
||||
{
|
||||
return (filter == GPUTextureFilter::Bilinear || filter == GPUTextureFilter::JINC2 || filter == GPUTextureFilter::xBR);
|
||||
}
|
||||
|
@ -148,42 +153,50 @@ bool GPU_HW::Initialize()
|
|||
return false;
|
||||
|
||||
const GPUDevice::Features features = g_gpu_device->GetFeatures();
|
||||
m_max_resolution_scale = g_gpu_device->GetMaxTextureSize() / VRAM_WIDTH;
|
||||
m_supports_dual_source_blend = features.dual_source_blend;
|
||||
m_supports_per_sample_shading = features.per_sample_shading;
|
||||
m_supports_disable_color_perspective = features.noperspective_interpolation;
|
||||
|
||||
m_resolution_scale = CalculateResolutionScale();
|
||||
m_multisamples = std::min(g_settings.gpu_multisamples, g_gpu_device->GetMaxMultisamples());
|
||||
m_per_sample_shading = g_settings.gpu_per_sample_shading && m_supports_per_sample_shading;
|
||||
m_per_sample_shading = g_settings.gpu_per_sample_shading && features.per_sample_shading;
|
||||
m_true_color = g_settings.gpu_true_color;
|
||||
m_scaled_dithering = g_settings.gpu_scaled_dithering;
|
||||
m_texture_filtering = g_settings.gpu_texture_filter;
|
||||
m_using_uv_limits = ShouldUseUVLimits();
|
||||
m_chroma_smoothing = g_settings.gpu_24bit_chroma_smoothing;
|
||||
m_downsample_mode = GetDownsampleMode(m_resolution_scale);
|
||||
m_disable_color_perspective = m_supports_disable_color_perspective && ShouldDisableColorPerspective();
|
||||
m_wireframe_mode = g_settings.gpu_wireframe_mode;
|
||||
m_disable_color_perspective = features.noperspective_interpolation && ShouldDisableColorPerspective();
|
||||
|
||||
if (m_multisamples != g_settings.gpu_multisamples)
|
||||
{
|
||||
Host::AddFormattedOSDMessage(20.0f, TRANSLATE("OSDMessage", "%ux MSAA is not supported, using %ux instead."),
|
||||
Host::AddFormattedOSDMessage(Host::OSD_CRITICAL_ERROR_DURATION,
|
||||
TRANSLATE("OSDMessage", "%ux MSAA is not supported, using %ux instead."),
|
||||
g_settings.gpu_multisamples, m_multisamples);
|
||||
}
|
||||
if (!m_per_sample_shading && g_settings.gpu_per_sample_shading)
|
||||
{
|
||||
Host::AddOSDMessage(TRANSLATE_STR("OSDMessage", "SSAA is not supported, using MSAA instead."), 20.0f);
|
||||
}
|
||||
if (!m_supports_dual_source_blend && TextureFilterRequiresDualSourceBlend(m_texture_filtering))
|
||||
if (!features.dual_source_blend && TextureFilterRequiresDualSourceBlend(m_texture_filtering))
|
||||
{
|
||||
Host::AddFormattedOSDMessage(
|
||||
20.0f, TRANSLATE("OSDMessage", "Texture filter '%s' is not supported with the current renderer."),
|
||||
Host::OSD_CRITICAL_ERROR_DURATION,
|
||||
TRANSLATE("OSDMessage", "Texture filter '%s' is not supported with the current renderer."),
|
||||
Settings::GetTextureFilterDisplayName(m_texture_filtering));
|
||||
m_texture_filtering = GPUTextureFilter::Nearest;
|
||||
}
|
||||
|
||||
if (!m_supports_disable_color_perspective && !ShouldDisableColorPerspective())
|
||||
if (!features.noperspective_interpolation && !ShouldDisableColorPerspective())
|
||||
Log_WarningPrint("Disable color perspective not supported, but should be used.");
|
||||
|
||||
if (!features.geometry_shaders && m_wireframe_mode != GPUWireframeMode::Disabled)
|
||||
{
|
||||
Host::AddOSDMessage(
|
||||
TRANSLATE("OSDMessage",
|
||||
"Geometry shaders are not supported by your GPU, and are required for wireframe rendering."),
|
||||
Host::OSD_CRITICAL_ERROR_DURATION);
|
||||
m_wireframe_mode = GPUWireframeMode::Disabled;
|
||||
}
|
||||
|
||||
m_pgxp_depth_buffer = g_settings.UsingPGXPDepthBuffer();
|
||||
|
||||
UpdateSoftwareRenderer(false);
|
||||
|
@ -290,12 +303,16 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
|||
{
|
||||
GPU::UpdateSettings(old_settings);
|
||||
|
||||
const GPUDevice::Features features = g_gpu_device->GetFeatures();
|
||||
|
||||
const u32 resolution_scale = CalculateResolutionScale();
|
||||
const u32 multisamples = std::min(g_settings.gpu_multisamples, g_gpu_device->GetMaxMultisamples());
|
||||
const bool per_sample_shading = g_settings.gpu_per_sample_shading && m_supports_per_sample_shading;
|
||||
const bool per_sample_shading = g_settings.gpu_per_sample_shading && features.noperspective_interpolation;
|
||||
const GPUDownsampleMode downsample_mode = GetDownsampleMode(resolution_scale);
|
||||
const GPUWireframeMode wireframe_mode =
|
||||
features.geometry_shaders ? g_settings.gpu_wireframe_mode : GPUWireframeMode::Disabled;
|
||||
const bool use_uv_limits = ShouldUseUVLimits();
|
||||
const bool disable_color_perspective = m_supports_disable_color_perspective && ShouldDisableColorPerspective();
|
||||
const bool disable_color_perspective = features.noperspective_interpolation && ShouldDisableColorPerspective();
|
||||
|
||||
// TODO: Use old_settings
|
||||
const bool framebuffer_changed =
|
||||
|
@ -305,7 +322,8 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
|||
m_true_color != g_settings.gpu_true_color || m_per_sample_shading != per_sample_shading ||
|
||||
m_scaled_dithering != g_settings.gpu_scaled_dithering || m_texture_filtering != g_settings.gpu_texture_filter ||
|
||||
m_using_uv_limits != use_uv_limits || m_chroma_smoothing != g_settings.gpu_24bit_chroma_smoothing ||
|
||||
m_downsample_mode != downsample_mode || m_pgxp_depth_buffer != g_settings.UsingPGXPDepthBuffer() ||
|
||||
m_downsample_mode != downsample_mode || m_wireframe_mode != wireframe_mode ||
|
||||
m_pgxp_depth_buffer != g_settings.UsingPGXPDepthBuffer() ||
|
||||
m_disable_color_perspective != disable_color_perspective);
|
||||
|
||||
if (m_resolution_scale != resolution_scale)
|
||||
|
@ -348,6 +366,7 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
|||
m_using_uv_limits = use_uv_limits;
|
||||
m_chroma_smoothing = g_settings.gpu_24bit_chroma_smoothing;
|
||||
m_downsample_mode = downsample_mode;
|
||||
m_wireframe_mode = wireframe_mode;
|
||||
m_disable_color_perspective = disable_color_perspective;
|
||||
|
||||
if (!m_supports_dual_source_blend && TextureFilterRequiresDualSourceBlend(m_texture_filtering))
|
||||
|
@ -387,10 +406,12 @@ void GPU_HW::UpdateSettings(const Settings& old_settings)
|
|||
|
||||
u32 GPU_HW::CalculateResolutionScale() const
|
||||
{
|
||||
const u32 max_resolution_scale = GetMaxResolutionScale();
|
||||
|
||||
u32 scale;
|
||||
if (g_settings.gpu_resolution_scale != 0)
|
||||
{
|
||||
scale = std::clamp<u32>(g_settings.gpu_resolution_scale, 1, m_max_resolution_scale);
|
||||
scale = std::clamp<u32>(g_settings.gpu_resolution_scale, 1, max_resolution_scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -404,7 +425,7 @@ u32 GPU_HW::CalculateResolutionScale() const
|
|||
static_cast<s32>(std::ceil(static_cast<float>(g_gpu_device->GetWindowHeight()) / height));
|
||||
Log_InfoPrintf("Height = %d, preferred scale = %d", height, preferred_scale);
|
||||
|
||||
scale = static_cast<u32>(std::clamp<s32>(preferred_scale, 1, m_max_resolution_scale));
|
||||
scale = static_cast<u32>(std::clamp<s32>(preferred_scale, 1, max_resolution_scale));
|
||||
}
|
||||
|
||||
if (g_settings.gpu_downsample_mode == GPUDownsampleMode::Adaptive && scale > 1 && !Common::IsPow2(scale))
|
||||
|
@ -474,7 +495,7 @@ std::tuple<u32, u32> GPU_HW::GetFullDisplayResolution(bool scaled /* = true */)
|
|||
void GPU_HW::PrintSettingsToLog()
|
||||
{
|
||||
Log_InfoPrintf("Resolution Scale: %u (%ux%u), maximum %u", m_resolution_scale, VRAM_WIDTH * m_resolution_scale,
|
||||
VRAM_HEIGHT * m_resolution_scale, m_max_resolution_scale);
|
||||
VRAM_HEIGHT * m_resolution_scale, GetMaxResolutionScale());
|
||||
Log_InfoPrintf("Multisampling: %ux%s", m_multisamples, m_per_sample_shading ? " (per sample shading)" : "");
|
||||
Log_InfoPrintf("Dithering: %s%s", m_true_color ? "Disabled" : "Enabled",
|
||||
(!m_true_color && m_scaled_dithering) ? " (Scaled)" : "");
|
||||
|
@ -483,6 +504,7 @@ void GPU_HW::PrintSettingsToLog()
|
|||
Log_InfoPrintf("Using UV limits: %s", m_using_uv_limits ? "YES" : "NO");
|
||||
Log_InfoPrintf("Depth buffer: %s", m_pgxp_depth_buffer ? "YES" : "NO");
|
||||
Log_InfoPrintf("Downsampling: %s", Settings::GetDownsampleModeDisplayName(m_downsample_mode));
|
||||
Log_InfoPrintf("Wireframe rendering: %s", Settings::GetGPUWireframeModeDisplayName(m_wireframe_mode));
|
||||
Log_InfoPrintf("Using software renderer for readbacks: %s", m_sw_renderer ? "YES" : "NO");
|
||||
}
|
||||
|
||||
|
@ -772,6 +794,39 @@ bool GPU_HW::CompilePipelines()
|
|||
}
|
||||
}
|
||||
|
||||
if (m_wireframe_mode != GPUWireframeMode::Disabled)
|
||||
{
|
||||
std::unique_ptr<GPUShader> gs =
|
||||
g_gpu_device->CreateShader(GPUShaderStage::Geometry, shadergen.GenerateWireframeGeometryShader());
|
||||
std::unique_ptr<GPUShader> fs =
|
||||
g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GenerateWireframeFragmentShader());
|
||||
if (!gs || !fs)
|
||||
return false;
|
||||
|
||||
GL_OBJECT_NAME(gs, "Batch Wireframe Geometry Shader");
|
||||
GL_OBJECT_NAME(fs, "Batch Wireframe Fragment Shader");
|
||||
|
||||
plconfig.input_layout.vertex_attributes =
|
||||
gsl::span<const GPUPipeline::VertexAttribute>(vertex_attributes, NUM_BATCH_VERTEX_ATTRIBUTES);
|
||||
plconfig.blend = (m_wireframe_mode == GPUWireframeMode::OverlayWireframe) ?
|
||||
GPUPipeline::BlendState::GetAlphaBlendingState() :
|
||||
GPUPipeline::BlendState::GetNoBlendingState();
|
||||
plconfig.blend.write_mask = 0x7;
|
||||
plconfig.depth = GPUPipeline::DepthState::GetNoTestsState();
|
||||
plconfig.vertex_shader = batch_vertex_shaders[0].get();
|
||||
plconfig.geometry_shader = gs.get();
|
||||
plconfig.fragment_shader = fs.get();
|
||||
|
||||
if (!(m_wireframe_pipeline = g_gpu_device->CreatePipeline(plconfig)))
|
||||
return false;
|
||||
|
||||
GL_OBJECT_NAME(m_wireframe_pipeline, "Batch Wireframe Pipeline");
|
||||
|
||||
plconfig.vertex_shader = nullptr;
|
||||
plconfig.geometry_shader = nullptr;
|
||||
plconfig.fragment_shader = nullptr;
|
||||
}
|
||||
|
||||
batch_shader_guard.Run();
|
||||
|
||||
std::unique_ptr<GPUShader> fullscreen_quad_vertex_shader =
|
||||
|
@ -1026,6 +1081,8 @@ void GPU_HW::DestroyPipelines()
|
|||
{
|
||||
static constexpr auto destroy = [](std::unique_ptr<GPUPipeline>& p) { p.reset(); };
|
||||
|
||||
m_wireframe_pipeline.reset();
|
||||
|
||||
m_batch_pipelines.enumerate(destroy);
|
||||
|
||||
m_vram_fill_pipelines.enumerate(destroy);
|
||||
|
@ -1136,7 +1193,7 @@ void GPU_HW::UnmapBatchVertexPointer(u32 used_vertices)
|
|||
m_batch_current_vertex_ptr = nullptr;
|
||||
}
|
||||
|
||||
void GPU_HW::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices)
|
||||
void GPU_HW::DrawBatchVertices(BatchRenderMode render_mode, u32 num_vertices, u32 base_vertex)
|
||||
{
|
||||
// [depth_test][render_mode][texture_mode][transparency_mode][dithering][interlacing]
|
||||
const u8 depth_test = m_batch.use_depth_buffer ? static_cast<u8>(2) : BoolToUInt8(m_batch.check_mask_before_draw);
|
||||
|
@ -2365,16 +2422,26 @@ void GPU_HW::FlushRender()
|
|||
m_batch_ubo_dirty = false;
|
||||
}
|
||||
|
||||
if (m_wireframe_mode != GPUWireframeMode::OnlyWireframe)
|
||||
{
|
||||
if (NeedsTwoPassRendering())
|
||||
{
|
||||
m_renderer_stats.num_batches += 2;
|
||||
DrawBatchVertices(BatchRenderMode::OnlyOpaque, m_batch_base_vertex, vertex_count);
|
||||
DrawBatchVertices(BatchRenderMode::OnlyTransparent, m_batch_base_vertex, vertex_count);
|
||||
DrawBatchVertices(BatchRenderMode::OnlyOpaque, vertex_count, m_batch_base_vertex);
|
||||
DrawBatchVertices(BatchRenderMode::OnlyTransparent, vertex_count, m_batch_base_vertex);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderer_stats.num_batches++;
|
||||
DrawBatchVertices(m_batch.GetRenderMode(), m_batch_base_vertex, vertex_count);
|
||||
DrawBatchVertices(m_batch.GetRenderMode(), vertex_count, m_batch_base_vertex);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_wireframe_mode != GPUWireframeMode::Disabled)
|
||||
{
|
||||
m_renderer_stats.num_batches++;
|
||||
g_gpu_device->SetPipeline(m_wireframe_pipeline.get());
|
||||
g_gpu_device->Draw(vertex_count, m_batch_base_vertex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ private:
|
|||
void SetScissor();
|
||||
void MapBatchVertexPointer(u32 required_vertices);
|
||||
void UnmapBatchVertexPointer(u32 used_vertices);
|
||||
void DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices);
|
||||
void DrawBatchVertices(BatchRenderMode render_mode, u32 num_vertices, u32 base_vertex);
|
||||
void ClearDisplay() override;
|
||||
void UpdateDisplay() override;
|
||||
|
||||
|
@ -266,24 +266,22 @@ private:
|
|||
|
||||
u32 m_resolution_scale = 1;
|
||||
u32 m_multisamples = 1;
|
||||
u32 m_max_resolution_scale = 1;
|
||||
bool m_true_color = true;
|
||||
|
||||
union
|
||||
{
|
||||
BitField<u8, bool, 0, 1> m_supports_per_sample_shading;
|
||||
BitField<u8, bool, 1, 1> m_supports_dual_source_blend;
|
||||
BitField<u8, bool, 2, 1> m_supports_disable_color_perspective;
|
||||
BitField<u8, bool, 3, 1> m_per_sample_shading;
|
||||
BitField<u8, bool, 4, 1> m_scaled_dithering;
|
||||
BitField<u8, bool, 5, 1> m_chroma_smoothing;
|
||||
BitField<u8, bool, 6, 1> m_disable_color_perspective;
|
||||
BitField<u8, bool, 0, 1> m_supports_dual_source_blend;
|
||||
BitField<u8, bool, 1, 1> m_per_sample_shading;
|
||||
BitField<u8, bool, 2, 1> m_scaled_dithering;
|
||||
BitField<u8, bool, 3, 1> m_chroma_smoothing;
|
||||
BitField<u8, bool, 4, 1> m_disable_color_perspective;
|
||||
|
||||
u8 bits = 0;
|
||||
};
|
||||
|
||||
GPUTextureFilter m_texture_filtering = GPUTextureFilter::Nearest;
|
||||
GPUDownsampleMode m_downsample_mode = GPUDownsampleMode::Disabled;
|
||||
GPUWireframeMode m_wireframe_mode = GPUWireframeMode::Disabled;
|
||||
bool m_true_color = true;
|
||||
bool m_using_uv_limits = false;
|
||||
bool m_pgxp_depth_buffer = false;
|
||||
|
||||
|
@ -298,6 +296,7 @@ private:
|
|||
|
||||
// [depth_test][render_mode][texture_mode][transparency_mode][dithering][interlacing]
|
||||
DimensionalArray<std::unique_ptr<GPUPipeline>, 2, 2, 5, 9, 4, 3> m_batch_pipelines{};
|
||||
std::unique_ptr<GPUPipeline> m_wireframe_pipeline;
|
||||
|
||||
// [wrapped][interlaced]
|
||||
DimensionalArray<std::unique_ptr<GPUPipeline>, 2, 2> m_vram_fill_pipelines{};
|
||||
|
|
|
@ -1087,6 +1087,96 @@ float3 SampleVRAM24Smoothed(uint2 icoords)
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GPU_HW_ShaderGen::GenerateWireframeGeometryShader()
|
||||
{
|
||||
std::stringstream ss;
|
||||
WriteHeader(ss);
|
||||
WriteCommonFunctions(ss);
|
||||
|
||||
if (m_glsl)
|
||||
{
|
||||
ss << R"(
|
||||
layout(triangles) in;
|
||||
layout(line_strip, max_vertices = 6) out;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
gl_Position = gl_in[1].gl_Position;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[2].gl_Position;
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
gl_Position = gl_in[2].gl_Position;
|
||||
EmitVertex();
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
}
|
||||
)";
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << R"(
|
||||
struct GSInput
|
||||
{
|
||||
float4 col0 : COLOR0;
|
||||
float4 pos : SV_Position;
|
||||
};
|
||||
|
||||
struct GSOutput
|
||||
{
|
||||
float4 pos : SV_Position;
|
||||
};
|
||||
|
||||
GSOutput GetVertex(GSInput vi)
|
||||
{
|
||||
GSOutput vo;
|
||||
vo.pos = vi.pos;
|
||||
return vo;
|
||||
}
|
||||
|
||||
[maxvertexcount(6)]
|
||||
void main(triangle GSInput input[3], inout LineStream<GSOutput> output)
|
||||
{
|
||||
output.Append(GetVertex(input[0]));
|
||||
output.Append(GetVertex(input[1]));
|
||||
output.RestartStrip();
|
||||
|
||||
output.Append(GetVertex(input[1]));
|
||||
output.Append(GetVertex(input[2]));
|
||||
output.RestartStrip();
|
||||
|
||||
output.Append(GetVertex(input[2]));
|
||||
output.Append(GetVertex(input[0]));
|
||||
output.RestartStrip();
|
||||
}
|
||||
)";
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GPU_HW_ShaderGen::GenerateWireframeFragmentShader()
|
||||
{
|
||||
std::stringstream ss;
|
||||
WriteHeader(ss);
|
||||
WriteCommonFunctions(ss);
|
||||
|
||||
DeclareFragmentEntryPoint(ss, 0, 0, {}, false, 1);
|
||||
ss << R"(
|
||||
{
|
||||
o_col0 = float4(1.0, 1.0, 1.0, 0.5);
|
||||
}
|
||||
)";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GPU_HW_ShaderGen::GenerateVRAMReadFragmentShader()
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
bool dithering, bool interlacing);
|
||||
std::string GenerateDisplayFragmentShader(bool depth_24bit, GPU_HW::InterlacedRenderMode interlace_mode,
|
||||
bool smooth_chroma);
|
||||
std::string GenerateWireframeGeometryShader();
|
||||
std::string GenerateWireframeFragmentShader();
|
||||
std::string GenerateVRAMReadFragmentShader();
|
||||
std::string GenerateVRAMWriteFragmentShader(bool use_ssbo);
|
||||
std::string GenerateVRAMCopyFragmentShader();
|
||||
|
|
|
@ -225,6 +225,10 @@ void Settings::Load(SettingsInterface& si)
|
|||
ParseDownsampleModeName(
|
||||
si.GetStringValue("GPU", "DownsampleMode", GetDownsampleModeName(DEFAULT_GPU_DOWNSAMPLE_MODE)).c_str())
|
||||
.value_or(DEFAULT_GPU_DOWNSAMPLE_MODE);
|
||||
gpu_wireframe_mode =
|
||||
ParseGPUWireframeMode(
|
||||
si.GetStringValue("GPU", "WireframeMode", GetGPUWireframeModeName(DEFAULT_GPU_WIREFRAME_MODE)).c_str())
|
||||
.value_or(DEFAULT_GPU_WIREFRAME_MODE);
|
||||
gpu_disable_interlacing = si.GetBoolValue("GPU", "DisableInterlacing", true);
|
||||
gpu_force_ntsc_timings = si.GetBoolValue("GPU", "ForceNTSCTimings", false);
|
||||
gpu_widescreen_hack = si.GetBoolValue("GPU", "WidescreenHack", false);
|
||||
|
@ -330,7 +334,7 @@ void Settings::Load(SettingsInterface& si)
|
|||
.c_str())
|
||||
.value_or(DEFAULT_CONTROLLER_1_TYPE);
|
||||
|
||||
const std::array<bool, 2> mtap_enabled = { {IsPort1MultitapEnabled(), IsPort2MultitapEnabled()} };
|
||||
const std::array<bool, 2> mtap_enabled = {{IsPort1MultitapEnabled(), IsPort2MultitapEnabled()}};
|
||||
for (u32 i = 1; i < NUM_CONTROLLER_AND_CARD_PORTS; i++)
|
||||
{
|
||||
// Ignore types when multitap not enabled
|
||||
|
@ -462,6 +466,7 @@ void Settings::Save(SettingsInterface& si) const
|
|||
si.SetBoolValue("GPU", "ScaledDithering", gpu_scaled_dithering);
|
||||
si.SetStringValue("GPU", "TextureFilter", GetTextureFilterName(gpu_texture_filter));
|
||||
si.SetStringValue("GPU", "DownsampleMode", GetDownsampleModeName(gpu_downsample_mode));
|
||||
si.SetStringValue("GPU", "WireframeMode", GetGPUWireframeModeName(gpu_wireframe_mode));
|
||||
si.SetBoolValue("GPU", "DisableInterlacing", gpu_disable_interlacing);
|
||||
si.SetBoolValue("GPU", "ForceNTSCTimings", gpu_force_ntsc_timings);
|
||||
si.SetBoolValue("GPU", "WidescreenHack", gpu_widescreen_hack);
|
||||
|
@ -1052,6 +1057,35 @@ const char* Settings::GetDownsampleModeDisplayName(GPUDownsampleMode mode)
|
|||
return Host::TranslateToCString("GPUDownsampleMode", s_downsample_mode_display_names[static_cast<int>(mode)]);
|
||||
}
|
||||
|
||||
static constexpr auto s_wireframe_mode_names = make_array("Disabled", "OverlayWireframe", "OnlyWireframe");
|
||||
static constexpr auto s_wireframe_mode_display_names =
|
||||
make_array(TRANSLATE_NOOP("GPUWireframeMode", "Disabled"), TRANSLATE_NOOP("GPUWireframeMode", "Overlay Wireframe"),
|
||||
TRANSLATE_NOOP("GPUWireframeMode", "Only Wireframe"));
|
||||
|
||||
std::optional<GPUWireframeMode> Settings::ParseGPUWireframeMode(const char* str)
|
||||
{
|
||||
int index = 0;
|
||||
for (const char* name : s_wireframe_mode_names)
|
||||
{
|
||||
if (StringUtil::Strcasecmp(name, str) == 0)
|
||||
return static_cast<GPUWireframeMode>(index);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const char* Settings::GetGPUWireframeModeName(GPUWireframeMode mode)
|
||||
{
|
||||
return s_wireframe_mode_names[static_cast<int>(mode)];
|
||||
}
|
||||
|
||||
const char* Settings::GetGPUWireframeModeDisplayName(GPUWireframeMode mode)
|
||||
{
|
||||
return Host::TranslateToCString("GPUWireframeMode", s_wireframe_mode_display_names[static_cast<int>(mode)]);
|
||||
}
|
||||
|
||||
static std::array<const char*, 3> s_display_crop_mode_names = {{"None", "Overscan", "Borders"}};
|
||||
static std::array<const char*, 3> s_display_crop_mode_display_names = {
|
||||
{TRANSLATE_NOOP("DisplayCropMode", "None"), TRANSLATE_NOOP("DisplayCropMode", "Only Overscan Area"),
|
||||
|
@ -1082,9 +1116,8 @@ const char* Settings::GetDisplayCropModeDisplayName(DisplayCropMode crop_mode)
|
|||
}
|
||||
|
||||
static std::array<const char*, static_cast<size_t>(DisplayAspectRatio::Count)> s_display_aspect_ratio_names = {
|
||||
{TRANSLATE_NOOP("DisplayAspectRatio", "Auto (Game Native)"),
|
||||
TRANSLATE_NOOP("DisplayAspectRatio", "Stretch To Fill"), TRANSLATE_NOOP("DisplayAspectRatio", "Custom"), "4:3",
|
||||
"16:9", "19:9", "20:9", "PAR 1:1"}};
|
||||
{TRANSLATE_NOOP("DisplayAspectRatio", "Auto (Game Native)"), TRANSLATE_NOOP("DisplayAspectRatio", "Stretch To Fill"),
|
||||
TRANSLATE_NOOP("DisplayAspectRatio", "Custom"), "4:3", "16:9", "19:9", "20:9", "PAR 1:1"}};
|
||||
static constexpr std::array<float, static_cast<size_t>(DisplayAspectRatio::Count)> s_display_aspect_ratio_values = {
|
||||
{-1.0f, -1.0f, -1.0f, 4.0f / 3.0f, 16.0f / 9.0f, 19.0f / 9.0f, 20.0f / 9.0f, -1.0f}};
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@ struct Settings
|
|||
bool gpu_scaled_dithering = true;
|
||||
GPUTextureFilter gpu_texture_filter = DEFAULT_GPU_TEXTURE_FILTER;
|
||||
GPUDownsampleMode gpu_downsample_mode = DEFAULT_GPU_DOWNSAMPLE_MODE;
|
||||
GPUWireframeMode gpu_wireframe_mode = DEFAULT_GPU_WIREFRAME_MODE;
|
||||
bool gpu_disable_interlacing = true;
|
||||
bool gpu_force_ntsc_timings = false;
|
||||
bool gpu_widescreen_hack = false;
|
||||
|
@ -373,6 +374,10 @@ struct Settings
|
|||
static const char* GetDownsampleModeName(GPUDownsampleMode mode);
|
||||
static const char* GetDownsampleModeDisplayName(GPUDownsampleMode mode);
|
||||
|
||||
static std::optional<GPUWireframeMode> ParseGPUWireframeMode(const char* str);
|
||||
static const char* GetGPUWireframeModeName(GPUWireframeMode mode);
|
||||
static const char* GetGPUWireframeModeDisplayName(GPUWireframeMode mode);
|
||||
|
||||
static std::optional<DisplayCropMode> ParseDisplayCropMode(const char* str);
|
||||
static const char* GetDisplayCropModeName(DisplayCropMode crop_mode);
|
||||
static const char* GetDisplayCropModeDisplayName(DisplayCropMode crop_mode);
|
||||
|
@ -421,6 +426,7 @@ struct Settings
|
|||
#endif
|
||||
static constexpr GPUTextureFilter DEFAULT_GPU_TEXTURE_FILTER = GPUTextureFilter::Nearest;
|
||||
static constexpr GPUDownsampleMode DEFAULT_GPU_DOWNSAMPLE_MODE = GPUDownsampleMode::Disabled;
|
||||
static constexpr GPUWireframeMode DEFAULT_GPU_WIREFRAME_MODE = GPUWireframeMode::Disabled;
|
||||
static constexpr ConsoleRegion DEFAULT_CONSOLE_REGION = ConsoleRegion::Auto;
|
||||
static constexpr float DEFAULT_GPU_PGXP_DEPTH_THRESHOLD = 300.0f;
|
||||
static constexpr float GPU_PGXP_DEPTH_THRESHOLD_SCALE = 4096.0f;
|
||||
|
|
|
@ -3589,6 +3589,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
|||
g_settings.gpu_force_ntsc_timings != old_settings.gpu_force_ntsc_timings ||
|
||||
g_settings.gpu_24bit_chroma_smoothing != old_settings.gpu_24bit_chroma_smoothing ||
|
||||
g_settings.gpu_downsample_mode != old_settings.gpu_downsample_mode ||
|
||||
g_settings.gpu_wireframe_mode != old_settings.gpu_wireframe_mode ||
|
||||
g_settings.display_crop_mode != old_settings.display_crop_mode ||
|
||||
g_settings.display_aspect_ratio != old_settings.display_aspect_ratio ||
|
||||
g_settings.display_alignment != old_settings.display_alignment ||
|
||||
|
|
|
@ -95,6 +95,14 @@ enum class GPUDownsampleMode : u8
|
|||
Count
|
||||
};
|
||||
|
||||
enum class GPUWireframeMode : u8
|
||||
{
|
||||
Disabled,
|
||||
OverlayWireframe,
|
||||
OnlyWireframe,
|
||||
Count,
|
||||
};
|
||||
|
||||
enum class DisplayCropMode : u8
|
||||
{
|
||||
None,
|
||||
|
|
|
@ -279,6 +279,11 @@ void AdvancedSettingsWidget::addTweakOptions()
|
|||
|
||||
addMSAATweakOption(m_dialog, m_ui.tweakOptionTable, tr("Multisample Antialiasing"));
|
||||
|
||||
addChoiceTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Wireframe Mode"), "GPU", "WireframeMode",
|
||||
Settings::ParseGPUWireframeMode, Settings::GetGPUWireframeModeName,
|
||||
Settings::GetGPUWireframeModeDisplayName, static_cast<u32>(GPUWireframeMode::Count),
|
||||
GPUWireframeMode::Disabled);
|
||||
|
||||
if (m_dialog->isPerGameSettings())
|
||||
{
|
||||
addIntRangeTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Display Active Start Offset"), "Display",
|
||||
|
@ -365,6 +370,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked()
|
|||
setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Apply compatibility settings
|
||||
setIntRangeTweakOption(m_ui.tweakOptionTable, i++, 0); // Display FPS limit
|
||||
setChoiceTweakOption(m_ui.tweakOptionTable, i++, 0); // Multisample antialiasing
|
||||
setChoiceTweakOption(m_ui.tweakOptionTable, i++, 0); // Wireframe mode
|
||||
setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // PGXP vertex cache
|
||||
setFloatRangeTweakOption(m_ui.tweakOptionTable, i++, -1.0f); // PGXP geometry tolerance
|
||||
setFloatRangeTweakOption(m_ui.tweakOptionTable, i++,
|
||||
|
|
|
@ -488,6 +488,8 @@ void ShaderGen::DeclareFragmentEntryPoint(
|
|||
bool noperspective_color /* = false */)
|
||||
{
|
||||
if (m_glsl)
|
||||
{
|
||||
if (num_color_inputs > 0 || num_texcoord_inputs > 0 || additional_inputs.size() > 0)
|
||||
{
|
||||
if (m_use_glsl_interface_blocks)
|
||||
{
|
||||
|
@ -526,6 +528,7 @@ void ShaderGen::DeclareFragmentEntryPoint(
|
|||
ss << qualifier_to_use << " in " << name << ";\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (declare_fragcoord)
|
||||
ss << "#define v_pos gl_FragCoord\n";
|
||||
|
|
Loading…
Reference in a new issue