VideoBackends:Metal: MSAA support
This commit is contained in:
parent
c0fd128171
commit
6ee0248eab
|
@ -111,6 +111,7 @@ void VideoBackend::FillBackendInfo()
|
||||||
g_Config.backend_info.bSupportsLodBiasInSampler = true;
|
g_Config.backend_info.bSupportsLodBiasInSampler = true;
|
||||||
g_Config.backend_info.bSupportsLogicOp = D3D::SupportsLogicOp(g_Config.iAdapter);
|
g_Config.backend_info.bSupportsLogicOp = D3D::SupportsLogicOp(g_Config.iAdapter);
|
||||||
g_Config.backend_info.bSupportsSettingObjectNames = true;
|
g_Config.backend_info.bSupportsSettingObjectNames = true;
|
||||||
|
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
|
||||||
|
|
||||||
g_Config.backend_info.Adapters = D3DCommon::GetAdapterNames();
|
g_Config.backend_info.Adapters = D3DCommon::GetAdapterNames();
|
||||||
g_Config.backend_info.AAModes = D3D::GetAAModes(g_Config.iAdapter);
|
g_Config.backend_info.AAModes = D3D::GetAAModes(g_Config.iAdapter);
|
||||||
|
|
|
@ -86,6 +86,7 @@ void VideoBackend::FillBackendInfo()
|
||||||
g_Config.backend_info.bSupportsTextureQueryLevels = true;
|
g_Config.backend_info.bSupportsTextureQueryLevels = true;
|
||||||
g_Config.backend_info.bSupportsLodBiasInSampler = true;
|
g_Config.backend_info.bSupportsLodBiasInSampler = true;
|
||||||
g_Config.backend_info.bSupportsSettingObjectNames = true;
|
g_Config.backend_info.bSupportsSettingObjectNames = true;
|
||||||
|
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
|
||||||
|
|
||||||
// We can only check texture support once we have a device.
|
// We can only check texture support once we have a device.
|
||||||
if (g_dx_context)
|
if (g_dx_context)
|
||||||
|
|
|
@ -141,7 +141,16 @@ void Metal::VideoBackend::InitBackendInfo()
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
Util::PopulateBackendInfo(&g_Config);
|
Util::PopulateBackendInfo(&g_Config);
|
||||||
Util::PopulateBackendInfoAdapters(&g_Config, Util::GetAdapterList());
|
auto adapters = Util::GetAdapterList();
|
||||||
|
Util::PopulateBackendInfoAdapters(&g_Config, adapters);
|
||||||
|
if (!adapters.empty())
|
||||||
|
{
|
||||||
|
// Use the selected adapter, or the first to fill features.
|
||||||
|
size_t index = static_cast<size_t>(g_Config.iAdapter);
|
||||||
|
if (index >= adapters.size())
|
||||||
|
index = 0;
|
||||||
|
Util::PopulateBackendInfoFeatures(&g_Config, adapters[index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -311,6 +311,7 @@ public:
|
||||||
fragment_shader = static_cast<const Shader*>(cfg.pixel_shader);
|
fragment_shader = static_cast<const Shader*>(cfg.pixel_shader);
|
||||||
framebuffer.color_texture_format = cfg.framebuffer_state.color_texture_format.Value();
|
framebuffer.color_texture_format = cfg.framebuffer_state.color_texture_format.Value();
|
||||||
framebuffer.depth_texture_format = cfg.framebuffer_state.depth_texture_format.Value();
|
framebuffer.depth_texture_format = cfg.framebuffer_state.depth_texture_format.Value();
|
||||||
|
framebuffer.samples = cfg.framebuffer_state.samples.Value();
|
||||||
blend.colorupdate = cfg.blending_state.colorupdate.Value();
|
blend.colorupdate = cfg.blending_state.colorupdate.Value();
|
||||||
blend.alphaupdate = cfg.blending_state.alphaupdate.Value();
|
blend.alphaupdate = cfg.blending_state.alphaupdate.Value();
|
||||||
if (cfg.blending_state.blendenable)
|
if (cfg.blending_state.blendenable)
|
||||||
|
@ -416,6 +417,7 @@ public:
|
||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
FramebufferState fs = config.framebuffer_state;
|
FramebufferState fs = config.framebuffer_state;
|
||||||
|
[desc setRasterSampleCount:fs.samples];
|
||||||
[color0 setPixelFormat:Util::FromAbstract(fs.color_texture_format)];
|
[color0 setPixelFormat:Util::FromAbstract(fs.color_texture_format)];
|
||||||
[desc setDepthAttachmentPixelFormat:Util::FromAbstract(fs.depth_texture_format)];
|
[desc setDepthAttachmentPixelFormat:Util::FromAbstract(fs.depth_texture_format)];
|
||||||
if (Util::HasStencil(fs.depth_texture_format))
|
if (Util::HasStencil(fs.depth_texture_format))
|
||||||
|
|
|
@ -68,6 +68,8 @@ void Metal::Util::PopulateBackendInfo(VideoConfig* config)
|
||||||
config->backend_info.bSupportsTextureQueryLevels = true;
|
config->backend_info.bSupportsTextureQueryLevels = true;
|
||||||
config->backend_info.bSupportsLodBiasInSampler = false;
|
config->backend_info.bSupportsLodBiasInSampler = false;
|
||||||
config->backend_info.bSupportsSettingObjectNames = true;
|
config->backend_info.bSupportsSettingObjectNames = true;
|
||||||
|
// Metal requires multisample resolve to be done on a render pass
|
||||||
|
config->backend_info.bSupportsPartialMultisampleResolve = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metal::Util::PopulateBackendInfoAdapters(VideoConfig* config,
|
void Metal::Util::PopulateBackendInfoAdapters(VideoConfig* config,
|
||||||
|
@ -201,6 +203,14 @@ void Metal::Util::PopulateBackendInfoFeatures(VideoConfig* config, id<MTLDevice>
|
||||||
config->backend_info.bSupportsBPTCTextures = supports_mac1;
|
config->backend_info.bSupportsBPTCTextures = supports_mac1;
|
||||||
config->backend_info.bSupportsFramebufferFetch = true;
|
config->backend_info.bSupportsFramebufferFetch = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
config->backend_info.AAModes.clear();
|
||||||
|
for (u32 i = 1; i <= 64; i <<= 1)
|
||||||
|
{
|
||||||
|
if ([device supportsTextureSampleCount:i])
|
||||||
|
config->backend_info.AAModes.push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
if (char* env = getenv("MTL_UNIFIED_MEMORY"))
|
if (char* env = getenv("MTL_UNIFIED_MEMORY"))
|
||||||
g_features.unified_memory = env[0] == '1' || env[0] == 'y' || env[0] == 'Y';
|
g_features.unified_memory = env[0] == '1' || env[0] == 'y' || env[0] == 'Y';
|
||||||
else if (@available(macOS 10.15, iOS 13.0, *))
|
else if (@available(macOS 10.15, iOS 13.0, *))
|
||||||
|
|
|
@ -59,6 +59,7 @@ void VideoBackend::InitBackendInfo()
|
||||||
g_Config.backend_info.bSupportsTextureQueryLevels = false;
|
g_Config.backend_info.bSupportsTextureQueryLevels = false;
|
||||||
g_Config.backend_info.bSupportsLodBiasInSampler = false;
|
g_Config.backend_info.bSupportsLodBiasInSampler = false;
|
||||||
g_Config.backend_info.bSupportsSettingObjectNames = false;
|
g_Config.backend_info.bSupportsSettingObjectNames = false;
|
||||||
|
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
|
||||||
|
|
||||||
// aamodes: We only support 1 sample, so no MSAA
|
// aamodes: We only support 1 sample, so no MSAA
|
||||||
g_Config.backend_info.Adapters.clear();
|
g_Config.backend_info.Adapters.clear();
|
||||||
|
|
|
@ -93,6 +93,7 @@ void VideoBackend::InitBackendInfo()
|
||||||
g_Config.backend_info.bSupportsShaderBinaries = false;
|
g_Config.backend_info.bSupportsShaderBinaries = false;
|
||||||
g_Config.backend_info.bSupportsPipelineCacheData = false;
|
g_Config.backend_info.bSupportsPipelineCacheData = false;
|
||||||
g_Config.backend_info.bSupportsLodBiasInSampler = true;
|
g_Config.backend_info.bSupportsLodBiasInSampler = true;
|
||||||
|
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
|
||||||
|
|
||||||
// TODO: There is a bug here, if texel buffers or SSBOs/atomics are not supported the graphics
|
// TODO: There is a bug here, if texel buffers or SSBOs/atomics are not supported the graphics
|
||||||
// options will show the option when it is not supported. The only way around this would be
|
// options will show the option when it is not supported. The only way around this would be
|
||||||
|
|
|
@ -88,6 +88,7 @@ void VideoSoftware::InitBackendInfo()
|
||||||
g_Config.backend_info.bSupportsTextureQueryLevels = false;
|
g_Config.backend_info.bSupportsTextureQueryLevels = false;
|
||||||
g_Config.backend_info.bSupportsLodBiasInSampler = false;
|
g_Config.backend_info.bSupportsLodBiasInSampler = false;
|
||||||
g_Config.backend_info.bSupportsSettingObjectNames = false;
|
g_Config.backend_info.bSupportsSettingObjectNames = false;
|
||||||
|
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
|
||||||
|
|
||||||
// aamodes
|
// aamodes
|
||||||
g_Config.backend_info.AAModes = {1};
|
g_Config.backend_info.AAModes = {1};
|
||||||
|
|
|
@ -294,6 +294,7 @@ void VulkanContext::PopulateBackendInfo(VideoConfig* config)
|
||||||
config->backend_info.bSupportsTextureQueryLevels = true; // Assumed support.
|
config->backend_info.bSupportsTextureQueryLevels = true; // Assumed support.
|
||||||
config->backend_info.bSupportsLodBiasInSampler = false; // Dependent on OS.
|
config->backend_info.bSupportsLodBiasInSampler = false; // Dependent on OS.
|
||||||
config->backend_info.bSupportsSettingObjectNames = false; // Dependent on features.
|
config->backend_info.bSupportsSettingObjectNames = false; // Dependent on features.
|
||||||
|
config->backend_info.bSupportsPartialMultisampleResolve = true; // Assumed support.
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list)
|
void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list)
|
||||||
|
|
|
@ -188,12 +188,23 @@ bool FramebufferManager::CreateEFBFramebuffer()
|
||||||
// Create resolved textures if MSAA is on
|
// Create resolved textures if MSAA is on
|
||||||
if (g_ActiveConfig.MultisamplingEnabled())
|
if (g_ActiveConfig.MultisamplingEnabled())
|
||||||
{
|
{
|
||||||
|
u32 flags = 0;
|
||||||
|
if (!g_ActiveConfig.backend_info.bSupportsPartialMultisampleResolve)
|
||||||
|
flags |= AbstractTextureFlag_RenderTarget;
|
||||||
m_efb_resolve_color_texture = g_renderer->CreateTexture(
|
m_efb_resolve_color_texture = g_renderer->CreateTexture(
|
||||||
TextureConfig(efb_color_texture_config.width, efb_color_texture_config.height, 1,
|
TextureConfig(efb_color_texture_config.width, efb_color_texture_config.height, 1,
|
||||||
efb_color_texture_config.layers, 1, efb_color_texture_config.format, 0),
|
efb_color_texture_config.layers, 1, efb_color_texture_config.format, flags),
|
||||||
"EFB color resolve texture");
|
"EFB color resolve texture");
|
||||||
if (!m_efb_resolve_color_texture)
|
if (!m_efb_resolve_color_texture)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!g_ActiveConfig.backend_info.bSupportsPartialMultisampleResolve)
|
||||||
|
{
|
||||||
|
m_efb_color_resolve_framebuffer =
|
||||||
|
g_renderer->CreateFramebuffer(m_efb_resolve_color_texture.get(), nullptr);
|
||||||
|
if (!m_efb_color_resolve_framebuffer)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We also need one to convert the D24S8 to R32F if that is being used (Adreno).
|
// We also need one to convert the D24S8 to R32F if that is being used (Adreno).
|
||||||
|
@ -248,12 +259,27 @@ AbstractTexture* FramebufferManager::ResolveEFBColorTexture(const MathUtil::Rect
|
||||||
clamped_region.ClampUL(0, 0, GetEFBWidth(), GetEFBHeight());
|
clamped_region.ClampUL(0, 0, GetEFBWidth(), GetEFBHeight());
|
||||||
|
|
||||||
// Resolve to our already-created texture.
|
// Resolve to our already-created texture.
|
||||||
for (u32 layer = 0; layer < GetEFBLayers(); layer++)
|
if (g_ActiveConfig.backend_info.bSupportsPartialMultisampleResolve)
|
||||||
{
|
{
|
||||||
m_efb_resolve_color_texture->ResolveFromTexture(m_efb_color_texture.get(), clamped_region,
|
for (u32 layer = 0; layer < GetEFBLayers(); layer++)
|
||||||
layer, 0);
|
{
|
||||||
|
m_efb_resolve_color_texture->ResolveFromTexture(m_efb_color_texture.get(), clamped_region,
|
||||||
|
layer, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_efb_color_texture->FinishedRendering();
|
||||||
|
g_renderer->BeginUtilityDrawing();
|
||||||
|
g_renderer->SetAndDiscardFramebuffer(m_efb_color_resolve_framebuffer.get());
|
||||||
|
g_renderer->SetPipeline(m_efb_color_resolve_pipeline.get());
|
||||||
|
g_renderer->SetTexture(0, m_efb_color_texture.get());
|
||||||
|
g_renderer->SetSamplerState(0, RenderState::GetPointSamplerState());
|
||||||
|
g_renderer->SetViewportAndScissor(clamped_region);
|
||||||
|
g_renderer->Draw(0, 3);
|
||||||
|
m_efb_resolve_color_texture->FinishedRendering();
|
||||||
|
g_renderer->EndUtilityDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_efb_resolve_color_texture->FinishedRendering();
|
m_efb_resolve_color_texture->FinishedRendering();
|
||||||
return m_efb_resolve_color_texture.get();
|
return m_efb_resolve_color_texture.get();
|
||||||
}
|
}
|
||||||
|
@ -487,6 +513,22 @@ bool FramebufferManager::CompileReadbackPipelines()
|
||||||
m_efb_depth_resolve_pipeline = g_renderer->CreatePipeline(config);
|
m_efb_depth_resolve_pipeline = g_renderer->CreatePipeline(config);
|
||||||
if (!m_efb_depth_resolve_pipeline)
|
if (!m_efb_depth_resolve_pipeline)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!g_ActiveConfig.backend_info.bSupportsPartialMultisampleResolve)
|
||||||
|
{
|
||||||
|
config.framebuffer_state.color_texture_format = GetEFBColorFormat();
|
||||||
|
auto color_resolve_shader = g_renderer->CreateShaderFromSource(
|
||||||
|
ShaderStage::Pixel,
|
||||||
|
FramebufferShaderGen::GenerateResolveColorPixelShader(GetEFBSamples()),
|
||||||
|
"Color resolve pixel shader");
|
||||||
|
if (!color_resolve_shader)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
config.pixel_shader = color_resolve_shader.get();
|
||||||
|
m_efb_color_resolve_pipeline = g_renderer->CreatePipeline(config);
|
||||||
|
if (!m_efb_color_resolve_pipeline)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EFB restore pipeline
|
// EFB restore pipeline
|
||||||
|
|
|
@ -170,7 +170,9 @@ protected:
|
||||||
|
|
||||||
std::unique_ptr<AbstractFramebuffer> m_efb_framebuffer;
|
std::unique_ptr<AbstractFramebuffer> m_efb_framebuffer;
|
||||||
std::unique_ptr<AbstractFramebuffer> m_efb_convert_framebuffer;
|
std::unique_ptr<AbstractFramebuffer> m_efb_convert_framebuffer;
|
||||||
|
std::unique_ptr<AbstractFramebuffer> m_efb_color_resolve_framebuffer;
|
||||||
std::unique_ptr<AbstractFramebuffer> m_efb_depth_resolve_framebuffer;
|
std::unique_ptr<AbstractFramebuffer> m_efb_depth_resolve_framebuffer;
|
||||||
|
std::unique_ptr<AbstractPipeline> m_efb_color_resolve_pipeline;
|
||||||
std::unique_ptr<AbstractPipeline> m_efb_depth_resolve_pipeline;
|
std::unique_ptr<AbstractPipeline> m_efb_depth_resolve_pipeline;
|
||||||
|
|
||||||
// Pipeline for restoring the contents of the EFB from a save state
|
// Pipeline for restoring the contents of the EFB from a save state
|
||||||
|
|
|
@ -338,6 +338,22 @@ std::string GenerateColorPixelShader()
|
||||||
return code.GetBuffer();
|
return code.GetBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GenerateResolveColorPixelShader(u32 samples)
|
||||||
|
{
|
||||||
|
ShaderCode code;
|
||||||
|
EmitSamplerDeclarations(code, 0, 1, true);
|
||||||
|
EmitPixelMainDeclaration(code, 1, 0);
|
||||||
|
code.Write("{{\n"
|
||||||
|
" int layer = int(v_tex0.z);\n"
|
||||||
|
" int3 coords = int3(int2(gl_FragCoord.xy), layer);\n"
|
||||||
|
" ocol0 = float4(0.0f);\n");
|
||||||
|
code.Write(" for (int i = 0; i < {}; i++)\n", samples);
|
||||||
|
code.Write(" ocol0 += texelFetch(samp0, coords, i);\n");
|
||||||
|
code.Write(" ocol0 /= {}.0f;\n", samples);
|
||||||
|
code.Write("}}\n");
|
||||||
|
return code.GetBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
std::string GenerateResolveDepthPixelShader(u32 samples)
|
std::string GenerateResolveDepthPixelShader(u32 samples)
|
||||||
{
|
{
|
||||||
ShaderCode code;
|
ShaderCode code;
|
||||||
|
|
|
@ -15,6 +15,7 @@ std::string GenerateScreenQuadVertexShader();
|
||||||
std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors);
|
std::string GeneratePassthroughGeometryShader(u32 num_tex, u32 num_colors);
|
||||||
std::string GenerateTextureCopyVertexShader();
|
std::string GenerateTextureCopyVertexShader();
|
||||||
std::string GenerateTextureCopyPixelShader();
|
std::string GenerateTextureCopyPixelShader();
|
||||||
|
std::string GenerateResolveColorPixelShader(u32 samples);
|
||||||
std::string GenerateResolveDepthPixelShader(u32 samples);
|
std::string GenerateResolveDepthPixelShader(u32 samples);
|
||||||
std::string GenerateClearVertexShader();
|
std::string GenerateClearVertexShader();
|
||||||
std::string GenerateEFBPokeVertexShader();
|
std::string GenerateEFBPokeVertexShader();
|
||||||
|
|
|
@ -238,6 +238,7 @@ struct VideoConfig final
|
||||||
bool bSupportsTextureQueryLevels = false;
|
bool bSupportsTextureQueryLevels = false;
|
||||||
bool bSupportsLodBiasInSampler = false;
|
bool bSupportsLodBiasInSampler = false;
|
||||||
bool bSupportsSettingObjectNames = false;
|
bool bSupportsSettingObjectNames = false;
|
||||||
|
bool bSupportsPartialMultisampleResolve = false;
|
||||||
} backend_info;
|
} backend_info;
|
||||||
|
|
||||||
// Utility
|
// Utility
|
||||||
|
|
Loading…
Reference in New Issue