diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 7c020a012..f43fb572a 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -109,7 +109,7 @@ GraphicsPipeline::GraphicsPipeline( const vk::PipelineMultisampleStateCreateInfo multisampling = { .rasterizationSamples = - LiverpoolToVK::NumSamples(key.num_samples, instance.GetFramebufferSampleCounts()), + instance.IsMixedSamplesSupported() ? vk::SampleCountFlagBits::e1 : key.num_samples, .sampleShadingEnable = false, }; @@ -212,7 +212,14 @@ GraphicsPipeline::GraphicsPipeline( }); } + const vk::AttachmentSampleCountInfoAMD mixed_samples = { + .colorAttachmentCount = key.num_color_attachments, + .pColorAttachmentSamples = key.color_samples.data(), + .depthStencilAttachmentSamples = key.depth_samples, + }; + const vk::PipelineRenderingCreateInfo pipeline_rendering_ci = { + .pNext = instance.IsMixedSamplesSupported() ? &mixed_samples : nullptr, .colorAttachmentCount = key.num_color_attachments, .pColorAttachmentFormats = key.color_formats.data(), .depthAttachmentFormat = key.depth_format, diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 59230ae46..b6862df6a 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -39,7 +39,9 @@ struct GraphicsPipelineKey { vk::Format depth_format; vk::Format stencil_format; - u32 num_samples; + vk::SampleCountFlagBits num_samples; + std::array color_samples; + vk::SampleCountFlagBits depth_samples; u32 mrt_mask; AmdGpu::PrimitiveType prim_type; Liverpool::PolygonMode polygon_mode; diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 9584329f0..a660f1050 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -283,6 +283,8 @@ bool Instance::CreateDevice() { LOG_INFO(Render_Vulkan, "- shaderImageFloat32AtomicMinMax: {}", shader_atomic_float2_features.shaderImageFloat32AtomicMinMax); } + nv_framebuffer_mixed_samples = add_extension(VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME); + amd_mixed_attachment_samples = add_extension(VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME); const bool calibrated_timestamps = TRACY_GPU_ENABLED ? add_extension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME) : false; diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 30848e8b7..6c0f56237 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -171,6 +171,12 @@ public: return shader_atomic_float2 && shader_atomic_float2_features.shaderImageFloat32AtomicMinMax; } + /// Returns true if VK_NV_framebuffer_mixed_samples or + /// VK_AMD_mixed_attachment_samples is supported + bool IsMixedSamplesSupported() const { + return nv_framebuffer_mixed_samples || amd_mixed_attachment_samples; + } + /// Returns true when geometry shaders are supported by the device bool IsGeometryStageSupported() const { return features.geometryShader; @@ -374,6 +380,8 @@ private: bool amd_gcn_shader{}; bool amd_shader_trinary_minmax{}; bool shader_atomic_float2{}; + bool nv_framebuffer_mixed_samples{}; + bool amd_mixed_attachment_samples{}; bool portability_subset{}; }; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index d7ad47a3c..89ca54585 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -278,8 +278,11 @@ bool PipelineCache::RefreshGraphicsKey() { vk::FormatFeatureFlagBits2::eDepthStencilAttachment); if (regs.depth_buffer.DepthValid()) { key.depth_format = depth_format; + key.depth_samples = LiverpoolToVK::NumSamples(regs.depth_buffer.NumSamples(), + instance.GetFramebufferSampleCounts()); } else { key.depth_format = vk::Format::eUndefined; + key.depth_samples = vk::SampleCountFlagBits::e1; } if (regs.depth_buffer.StencilValid()) { key.stencil_format = depth_format; @@ -290,7 +293,8 @@ bool PipelineCache::RefreshGraphicsKey() { key.prim_type = regs.primitive_type; key.polygon_mode = regs.polygon_control.PolyMode(); key.clip_space = regs.clipper_control.clip_space; - key.num_samples = regs.NumSamples(); + key.num_samples = + LiverpoolToVK::NumSamples(regs.NumSamples(), instance.GetFramebufferSampleCounts()); const bool skip_cb_binding = regs.color_control.mode == AmdGpu::Liverpool::ColorControl::OperationMode::Disable; @@ -301,6 +305,7 @@ bool PipelineCache::RefreshGraphicsKey() { key.num_color_attachments = 0; key.color_formats.fill(vk::Format::eUndefined); key.color_buffers.fill({}); + key.color_samples.fill(vk::SampleCountFlagBits::e1); key.blend_controls.fill({}); key.write_masks.fill({}); key.vertex_buffer_formats.fill(vk::Format::eUndefined); @@ -335,6 +340,8 @@ bool PipelineCache::RefreshGraphicsKey() { col_buf.GetDataFmt() == AmdGpu::DataFormat::Format8_8 || col_buf.GetDataFmt() == AmdGpu::DataFormat::Format8_8_8_8); + key.color_samples[remapped_cb] = + LiverpoolToVK::NumSamples(col_buf.NumSamples(), instance.GetFramebufferSampleCounts()); key.color_formats[remapped_cb] = LiverpoolToVK::SurfaceFormat(col_buf.GetDataFmt(), col_buf.GetNumberFmt()); key.color_buffers[remapped_cb] = Shader::PsColorBuffer{