|
|
|
|
@ -105,9 +105,9 @@ public:
|
|
|
|
|
}
|
|
|
|
|
~ShaderCompileProgressTracker() = default;
|
|
|
|
|
|
|
|
|
|
void Increment()
|
|
|
|
|
void Increment(u32 progress = 1)
|
|
|
|
|
{
|
|
|
|
|
m_progress++;
|
|
|
|
|
m_progress += progress;
|
|
|
|
|
|
|
|
|
|
const u64 tv = Common::Timer::GetCurrentValue();
|
|
|
|
|
if ((tv - m_start_time) >= m_min_time && (tv - m_last_update_time) >= m_update_interval)
|
|
|
|
|
@ -209,6 +209,7 @@ bool GPU_HW::Initialize()
|
|
|
|
|
m_resolution_scale = CalculateResolutionScale();
|
|
|
|
|
m_multisamples = std::min(g_settings.gpu_multisamples, g_gpu_device->GetMaxMultisamples());
|
|
|
|
|
m_supports_dual_source_blend = features.dual_source_blend;
|
|
|
|
|
m_supports_framebuffer_fetch = features.framebuffer_fetch;
|
|
|
|
|
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;
|
|
|
|
|
@ -457,7 +458,7 @@ void GPU_HW::CheckSettings()
|
|
|
|
|
TRANSLATE_STR("GPU_HW", "SSAA is not supported, using MSAA instead."),
|
|
|
|
|
Host::OSD_ERROR_DURATION);
|
|
|
|
|
}
|
|
|
|
|
if (!features.dual_source_blend && IsBlendedTextureFiltering(m_texture_filtering))
|
|
|
|
|
if (!features.dual_source_blend && !features.framebuffer_fetch && IsBlendedTextureFiltering(m_texture_filtering))
|
|
|
|
|
{
|
|
|
|
|
Host::AddIconOSDMessage(
|
|
|
|
|
"TextureFilterUnsupported", ICON_FA_EXCLAMATION_TRIANGLE,
|
|
|
|
|
@ -738,16 +739,17 @@ bool GPU_HW::CompilePipelines()
|
|
|
|
|
const GPUDevice::Features features = g_gpu_device->GetFeatures();
|
|
|
|
|
GPU_HW_ShaderGen shadergen(g_gpu_device->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
|
|
|
|
|
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
|
|
|
|
|
m_pgxp_depth_buffer, m_disable_color_perspective, m_supports_dual_source_blend);
|
|
|
|
|
m_pgxp_depth_buffer, m_disable_color_perspective, m_supports_dual_source_blend,
|
|
|
|
|
m_supports_framebuffer_fetch);
|
|
|
|
|
|
|
|
|
|
ShaderCompileProgressTracker progress("Compiling Pipelines", 2 + (4 * 9 * 2 * 2) + (3 * 4 * 5 * 9 * 2 * 2) + 1 + 2 +
|
|
|
|
|
(2 * 2) + 2 + 1 + 1 + (2 * 3) + 1);
|
|
|
|
|
ShaderCompileProgressTracker progress("Compiling Pipelines", 2 + (4 * 5 * 9 * 2 * 2) + (3 * 4 * 5 * 9 * 2 * 2) + 1 +
|
|
|
|
|
2 + (2 * 2) + 2 + 1 + 1 + (2 * 3) + 1);
|
|
|
|
|
|
|
|
|
|
// vertex shaders - [textured]
|
|
|
|
|
// fragment shaders - [render_mode][texture_mode][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>, 2, 2, 9, 4> batch_fragment_shaders{};
|
|
|
|
|
DimensionalArray<std::unique_ptr<GPUShader>, 2, 2, 9, 5, 4> 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);
|
|
|
|
|
@ -764,6 +766,28 @@ bool GPU_HW::CompilePipelines()
|
|
|
|
|
|
|
|
|
|
for (u8 render_mode = 0; render_mode < 4; render_mode++)
|
|
|
|
|
{
|
|
|
|
|
for (u8 transparency_mode = 0; transparency_mode < 5; transparency_mode++)
|
|
|
|
|
{
|
|
|
|
|
if (m_supports_framebuffer_fetch)
|
|
|
|
|
{
|
|
|
|
|
// Don't need multipass shaders.
|
|
|
|
|
if (render_mode != static_cast<u8>(BatchRenderMode::TransparencyDisabled) &&
|
|
|
|
|
render_mode != static_cast<u8>(BatchRenderMode::TransparentAndOpaque))
|
|
|
|
|
{
|
|
|
|
|
progress.Increment(2 * 2 * 9);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Can't generate shader blending.
|
|
|
|
|
if (transparency_mode != static_cast<u8>(GPUTransparencyMode::Disabled))
|
|
|
|
|
{
|
|
|
|
|
progress.Increment(2 * 2 * 9);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (u8 texture_mode = 0; texture_mode < 9; texture_mode++)
|
|
|
|
|
{
|
|
|
|
|
for (u8 dithering = 0; dithering < 2; dithering++)
|
|
|
|
|
@ -771,10 +795,11 @@ bool GPU_HW::CompilePipelines()
|
|
|
|
|
for (u8 interlacing = 0; interlacing < 2; interlacing++)
|
|
|
|
|
{
|
|
|
|
|
const std::string fs = shadergen.GenerateBatchFragmentShader(
|
|
|
|
|
static_cast<BatchRenderMode>(render_mode), static_cast<GPUTextureMode>(texture_mode),
|
|
|
|
|
ConvertToBoolUnchecked(dithering), ConvertToBoolUnchecked(interlacing));
|
|
|
|
|
static_cast<BatchRenderMode>(render_mode), static_cast<GPUTransparencyMode>(transparency_mode),
|
|
|
|
|
static_cast<GPUTextureMode>(texture_mode), ConvertToBoolUnchecked(dithering),
|
|
|
|
|
ConvertToBoolUnchecked(interlacing));
|
|
|
|
|
|
|
|
|
|
if (!(batch_fragment_shaders[render_mode][texture_mode][dithering][interlacing] =
|
|
|
|
|
if (!(batch_fragment_shaders[render_mode][transparency_mode][texture_mode][dithering][interlacing] =
|
|
|
|
|
g_gpu_device->CreateShader(GPUShaderStage::Fragment, fs)))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
@ -785,6 +810,7 @@ bool GPU_HW::CompilePipelines()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static constexpr GPUPipeline::VertexAttribute vertex_attributes[] = {
|
|
|
|
|
GPUPipeline::VertexAttribute::Make(0, GPUPipeline::VertexAttribute::Semantic::Position, 0,
|
|
|
|
|
@ -818,6 +844,17 @@ bool GPU_HW::CompilePipelines()
|
|
|
|
|
{
|
|
|
|
|
for (u8 render_mode = 0; render_mode < 4; render_mode++)
|
|
|
|
|
{
|
|
|
|
|
if (m_supports_framebuffer_fetch)
|
|
|
|
|
{
|
|
|
|
|
// Don't need multipass shaders.
|
|
|
|
|
if (render_mode != static_cast<u8>(BatchRenderMode::TransparencyDisabled) &&
|
|
|
|
|
render_mode != static_cast<u8>(BatchRenderMode::TransparentAndOpaque))
|
|
|
|
|
{
|
|
|
|
|
progress.Increment(2 * 2 * 9 * 5);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (u8 transparency_mode = 0; transparency_mode < 5; transparency_mode++)
|
|
|
|
|
{
|
|
|
|
|
for (u8 texture_mode = 0; texture_mode < 9; texture_mode++)
|
|
|
|
|
@ -830,6 +867,8 @@ bool GPU_HW::CompilePipelines()
|
|
|
|
|
GPUPipeline::DepthFunc::Always, GPUPipeline::DepthFunc::GreaterEqual,
|
|
|
|
|
GPUPipeline::DepthFunc::LessEqual};
|
|
|
|
|
const bool textured = (static_cast<GPUTextureMode>(texture_mode) != GPUTextureMode::Disabled);
|
|
|
|
|
const bool use_shader_blending =
|
|
|
|
|
(textured && NeedsShaderBlending(static_cast<GPUTransparencyMode>(transparency_mode)));
|
|
|
|
|
|
|
|
|
|
plconfig.input_layout.vertex_attributes =
|
|
|
|
|
textured ?
|
|
|
|
|
@ -841,16 +880,21 @@ bool GPU_HW::CompilePipelines()
|
|
|
|
|
|
|
|
|
|
plconfig.vertex_shader = batch_vertex_shaders[BoolToUInt8(textured)].get();
|
|
|
|
|
plconfig.fragment_shader =
|
|
|
|
|
batch_fragment_shaders[render_mode][texture_mode][dithering][interlacing].get();
|
|
|
|
|
batch_fragment_shaders[render_mode]
|
|
|
|
|
[use_shader_blending ? transparency_mode :
|
|
|
|
|
static_cast<u8>(GPUTransparencyMode::Disabled)]
|
|
|
|
|
[texture_mode][dithering][interlacing]
|
|
|
|
|
.get();
|
|
|
|
|
|
|
|
|
|
plconfig.depth.depth_test = depth_test_values[depth_test];
|
|
|
|
|
plconfig.depth.depth_write = !m_pgxp_depth_buffer || depth_test != 0;
|
|
|
|
|
plconfig.blend = GPUPipeline::BlendState::GetNoBlendingState();
|
|
|
|
|
|
|
|
|
|
if ((static_cast<GPUTransparencyMode>(transparency_mode) != GPUTransparencyMode::Disabled &&
|
|
|
|
|
if (!use_shader_blending &&
|
|
|
|
|
((static_cast<GPUTransparencyMode>(transparency_mode) != GPUTransparencyMode::Disabled &&
|
|
|
|
|
(static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::TransparencyDisabled &&
|
|
|
|
|
static_cast<BatchRenderMode>(render_mode) != BatchRenderMode::OnlyOpaque)) ||
|
|
|
|
|
IsBlendedTextureFiltering(m_texture_filtering))
|
|
|
|
|
(textured && IsBlendedTextureFiltering(m_texture_filtering))))
|
|
|
|
|
{
|
|
|
|
|
plconfig.blend.enable = true;
|
|
|
|
|
plconfig.blend.src_alpha_blend = GPUPipeline::BlendFunc::One;
|
|
|
|
|
@ -2051,17 +2095,24 @@ GPU_HW::InterlacedRenderMode GPU_HW::GetInterlacedRenderMode() const
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ALWAYS_INLINE bool GPU_HW::NeedsTwoPassRendering() const
|
|
|
|
|
ALWAYS_INLINE_RELEASE bool GPU_HW::NeedsTwoPassRendering() const
|
|
|
|
|
{
|
|
|
|
|
// We need two-pass rendering when using BG-FG blending and texturing, as the transparency can be enabled
|
|
|
|
|
// on a per-pixel basis, and the opaque pixels shouldn't be blended at all.
|
|
|
|
|
|
|
|
|
|
// TODO: see if there's a better way we can do this. definitely can with fbfetch.
|
|
|
|
|
return (m_batch.texture_mode != GPUTextureMode::Disabled &&
|
|
|
|
|
return (m_batch.texture_mode != GPUTextureMode::Disabled && !m_supports_framebuffer_fetch &&
|
|
|
|
|
(m_batch.transparency_mode == GPUTransparencyMode::BackgroundMinusForeground ||
|
|
|
|
|
(!m_supports_dual_source_blend && m_batch.transparency_mode != GPUTransparencyMode::Disabled)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ALWAYS_INLINE_RELEASE bool GPU_HW::NeedsShaderBlending(GPUTransparencyMode transparency) const
|
|
|
|
|
{
|
|
|
|
|
return (m_supports_framebuffer_fetch &&
|
|
|
|
|
(transparency == GPUTransparencyMode::BackgroundMinusForeground ||
|
|
|
|
|
(!m_supports_dual_source_blend &&
|
|
|
|
|
(transparency != GPUTransparencyMode::Disabled || IsBlendedTextureFiltering(m_texture_filtering)))));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ALWAYS_INLINE u32 GPU_HW::GetBatchVertexSpace() const
|
|
|
|
|
{
|
|
|
|
|
return static_cast<u32>(m_batch_end_vertex_ptr - m_batch_current_vertex_ptr);
|
|
|
|
|
@ -2484,7 +2535,8 @@ void GPU_HW::DispatchRenderCommand()
|
|
|
|
|
EnsureVertexBufferSpaceForCurrentCommand();
|
|
|
|
|
|
|
|
|
|
// transparency mode change
|
|
|
|
|
if (m_batch.transparency_mode != transparency_mode && transparency_mode != GPUTransparencyMode::Disabled)
|
|
|
|
|
if (transparency_mode != GPUTransparencyMode::Disabled &&
|
|
|
|
|
(texture_mode == GPUTextureMode::Disabled || !NeedsShaderBlending(transparency_mode)))
|
|
|
|
|
{
|
|
|
|
|
static constexpr float transparent_alpha[4][2] = {{0.5f, 0.5f}, {1.0f, 1.0f}, {1.0f, 1.0f}, {0.25f, 1.0f}};
|
|
|
|
|
|
|
|
|
|
|