diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index 330409918..e40e4e99f 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -431,8 +431,10 @@ void RasterizerCache::CopySurface(Surface& src_surface, Surface& dst_surface, const u32 src_scale = src_surface.res_scale; const u32 dst_scale = dst_surface.res_scale; - if (src_scale > dst_scale) { - dst_surface.ScaleUp(src_scale); + const u32 src_sample_count = src_surface.sample_count; + const u32 dst_sample_count = dst_surface.sample_count; + if ((src_scale > dst_scale) || (src_sample_count > dst_sample_count)) { + dst_surface.ScaleUp(src_scale, src_sample_count); } const auto src_rect = src_surface.GetScaledSubRect(subrect_params); @@ -1171,8 +1173,9 @@ bool RasterizerCache::ValidateByReinterpretation(Surface& surface, SurfacePar return false; } const u32 res_scale = src_surface.res_scale; - if (res_scale > surface.res_scale) { - surface.ScaleUp(res_scale); + const u8 sample_count = src_surface.sample_count; + if ((res_scale > surface.res_scale) || (sample_count > surface.sample_count)) { + surface.ScaleUp(res_scale, sample_count); } const PAddr addr = boost::icl::lower(interval); const SurfaceParams copy_params = surface.FromInterval(copy_interval); @@ -1349,8 +1352,8 @@ SurfaceId RasterizerCache::CreateSurface(const SurfaceParams& params) { return surface_id; }(); Surface& surface = slot_surfaces[surface_id]; - if (params.res_scale > surface.res_scale) { - surface.ScaleUp(params.res_scale); + if ((params.res_scale > surface.res_scale) || (params.sample_count > surface.sample_count)) { + surface.ScaleUp(params.res_scale, params.sample_count); } surface.MarkInvalid(surface.GetInterval()); return surface_id; diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.cpp b/src/video_core/renderer_opengl/gl_texture_runtime.cpp index f24fe10ac..57c169abb 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.cpp +++ b/src/video_core/renderer_opengl/gl_texture_runtime.cpp @@ -550,23 +550,33 @@ void Surface::Attach(GLenum target, u32 level, u32 layer, bool scaled) { } } -void Surface::ScaleUp(u32 new_scale) { - if (res_scale == new_scale || new_scale == 1) { +void Surface::ScaleUp(u32 new_scale, u8 new_sample_count) { + if (res_scale == new_scale) { + return; + } + if (sample_count == new_sample_count) { return; } res_scale = new_scale; - textures[1] = MakeHandle(GL_TEXTURE_2D, GetScaledWidth(), GetScaledHeight(), levels, tuple, - DebugName(true)); - for (u32 level = 0; level < levels; level++) { - const VideoCore::TextureBlit blit = { - .src_level = level, - .dst_level = level, - .src_rect = GetRect(level), - .dst_rect = GetScaledRect(level), - }; - BlitScale(blit, true); + if (res_scale > 1) { + + textures[1] = MakeHandle(GL_TEXTURE_2D, GetScaledWidth(), GetScaledHeight(), levels, tuple, + DebugName(true)); + for (u32 level = 0; level < levels; level++) { + const VideoCore::TextureBlit blit = { + .src_level = level, + .dst_level = level, + .src_rect = GetRect(level), + .dst_rect = GetScaledRect(level), + }; + BlitScale(blit, true); + } + } + + if (new_sample_count > 1) { + // Todo(wunk): OpenGL MSAA } } diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.h b/src/video_core/renderer_opengl/gl_texture_runtime.h index 9fdc77bc5..c377a929e 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.h +++ b/src/video_core/renderer_opengl/gl_texture_runtime.h @@ -126,8 +126,8 @@ public: /// Attaches a handle of surface to the specified framebuffer target void Attach(GLenum target, u32 level, u32 layer, bool scaled = true); - /// Scales up the surface to match the new resolution scale. - void ScaleUp(u32 new_scale); + /// Scales up the surface to match the new resolution scale and sample-count. + void ScaleUp(u32 new_scale, u8 new_sample_count); /// Returns the bpp of the internal surface format u32 GetInternalBytesPerPixel() const; diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp index cdae7a647..295c93450 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp @@ -1084,12 +1084,16 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, }); } -void Surface::ScaleUp(u32 new_scale) { - if (res_scale == new_scale || new_scale == 1) { +void Surface::ScaleUp(u32 new_scale, u8 new_sample_count) { + if (res_scale == new_scale) { + return; + } + if (sample_count == new_sample_count) { return; } res_scale = new_scale; + sample_count = new_sample_count; const bool is_mutable = pixel_format == VideoCore::PixelFormat::RGBA8; @@ -1101,27 +1105,35 @@ void Surface::ScaleUp(u32 new_scale) { flags |= vk::ImageCreateFlagBits::eMutableFormat; } - handles[1] = MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, - traits.native, vk::SampleCountFlagBits::e1, traits.usage, flags, - traits.aspect, false, DebugName(true)); + if (res_scale > 1) { + handles[1] = MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, + traits.native, vk::SampleCountFlagBits::e1, traits.usage, flags, + traits.aspect, false, DebugName(true)); - runtime->renderpass_cache.EndRendering(); - scheduler->Record( - [raw_images = std::array{Image()}, aspect = traits.aspect](vk::CommandBuffer cmdbuf) { - const auto barriers = MakeInitBarriers(aspect, raw_images); - cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, - vk::PipelineStageFlagBits::eTopOfPipe, - vk::DependencyFlagBits::eByRegion, {}, {}, barriers); - }); - LOG_INFO(HW_GPU, "Surface scale up!"); - for (u32 level = 0; level < levels; level++) { - const VideoCore::TextureBlit blit = { - .src_level = level, - .dst_level = level, - .src_rect = GetRect(level), - .dst_rect = GetScaledRect(level), - }; - BlitScale(blit, true); + runtime->renderpass_cache.EndRendering(); + scheduler->Record( + [raw_images = std::array{Image()}, aspect = traits.aspect](vk::CommandBuffer cmdbuf) { + const auto barriers = MakeInitBarriers(aspect, raw_images); + cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, + vk::PipelineStageFlagBits::eTopOfPipe, + vk::DependencyFlagBits::eByRegion, {}, {}, barriers); + }); + LOG_INFO(HW_GPU, "Surface scale up!"); + for (u32 level = 0; level < levels; level++) { + const VideoCore::TextureBlit blit = { + .src_level = level, + .dst_level = level, + .src_rect = GetRect(level), + .dst_rect = GetScaledRect(level), + }; + BlitScale(blit, true); + } + } + + if (sample_count > 1) { + handles[3] = MakeHandle(instance, GetScaledWidth(), GetScaledHeight(), levels, texture_type, + traits.native, vk::SampleCountFlagBits(sample_count), traits.usage, + flags, traits.aspect, false, DebugName(true, false, sample_count)); } } @@ -1487,8 +1499,8 @@ void Surface::BlitScale(const VideoCore::TextureBlit& blit, bool up_scale) { Framebuffer::Framebuffer(TextureRuntime& runtime, const VideoCore::FramebufferParams& params, Surface* color, Surface* depth) - : VideoCore::FramebufferParams{params}, res_scale{color ? color->res_scale - : (depth ? depth->res_scale : 1u)}, + : VideoCore::FramebufferParams{params}, + res_scale{color ? color->res_scale : (depth ? depth->res_scale : 1u)}, sample_count{params.sample_count} { auto& renderpass_cache = runtime.GetRenderpassCache(); if (shadow_rendering && !color) { diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.h b/src/video_core/renderer_vulkan/vk_texture_runtime.h index 8d6fd3044..990618e91 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.h +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.h @@ -156,8 +156,8 @@ public: void Download(const VideoCore::BufferTextureCopy& download, const VideoCore::StagingData& staging); - /// Scales up the surface to match the new resolution scale. - void ScaleUp(u32 new_scale); + /// Scales up the surface to match the new resolution scale and sample-count. + void ScaleUp(u32 new_scale, u8 new_sample_count); /// Returns the bpp of the internal surface format u32 GetInternalBytesPerPixel() const;