From 39ca721cac41da28662cbff4d219362c9aac63a3 Mon Sep 17 00:00:00 2001 From: emufan4568 Date: Mon, 8 Aug 2022 14:48:55 +0300 Subject: [PATCH] rasterizer_cache: Return a framebuffer handle from GetFramebufferSurfaces --- src/video_core/common/framebuffer.h | 18 ++++-- src/video_core/common/rasterizer_cache.cpp | 55 ++++++++++++------- src/video_core/common/rasterizer_cache.h | 4 +- .../renderer_vulkan/vk_framebuffer.cpp | 4 +- .../renderer_vulkan/vk_framebuffer.h | 2 +- 5 files changed, 53 insertions(+), 30 deletions(-) diff --git a/src/video_core/common/framebuffer.h b/src/video_core/common/framebuffer.h index e6fa212b0..f48dfcc51 100644 --- a/src/video_core/common/framebuffer.h +++ b/src/video_core/common/framebuffer.h @@ -44,24 +44,30 @@ public: FramebufferBase& operator=(const FramebufferBase&) = delete; // Clears the attachments bound to the framebuffer - virtual void DoClear(Common::Rectangle rect, Common::Vec4f color, float depth, u8 stencil) = 0; + virtual void DoClear(Common::Vec4f color, float depth, u8 stencil) = 0; - /// Returns an immutable reference to the color attachment - const TextureHandle& GetColorAttachment() const { + // Returns an immutable reference to the color attachment + TextureHandle GetColorAttachment() const { return info.color; } - /// Returns an immutable reference to the depth/stencil attachment - const TextureHandle& GetDepthStencilAttachment() const { + // Returns an immutable reference to the depth/stencil attachment + TextureHandle GetDepthStencilAttachment() const { return info.depth_stencil; } - /// Returns how many samples the framebuffer takes + // Sets the area of the framebuffer affected by draw operations + void SetDrawRect(Rect2D rect) { + draw_rect = rect; + } + + // Returns how many samples the framebuffer takes MSAASamples GetMSAASamples() const { return info.samples; } protected: + Rect2D draw_rect; FramebufferInfo info; }; diff --git a/src/video_core/common/rasterizer_cache.cpp b/src/video_core/common/rasterizer_cache.cpp index fbf6a569f..8764c8707 100644 --- a/src/video_core/common/rasterizer_cache.cpp +++ b/src/video_core/common/rasterizer_cache.cpp @@ -252,6 +252,7 @@ bool RasterizerCache::FillSurface(const Surface& surface, const u8* fill_data, C framebuffer_cache.emplace(framebuffer_info, framebuffer); } + framebuffer->SetDrawRect(fill_rect); surface->InvalidateAllWatcher(); if (surface->type == SurfaceType::Color || surface->type == SurfaceType::Texture) { @@ -259,7 +260,7 @@ bool RasterizerCache::FillSurface(const Surface& surface, const u8* fill_data, C tex_info.format = static_cast(surface->pixel_format); Common::Vec4f color_values = Pica::Texture::LookupTexture(fill_data, 0, 0, tex_info) / 255.f; - framebuffer->DoClear(fill_rect, color_values, 0.0f, 0); + framebuffer->DoClear(color_values, 0.0f, 0); } else if (surface->type == SurfaceType::Depth) { u32 depth_32bit = 0; float depth_float; @@ -275,7 +276,7 @@ bool RasterizerCache::FillSurface(const Surface& surface, const u8* fill_data, C UNREACHABLE(); } - framebuffer->DoClear(fill_rect, {}, depth_float, 0); + framebuffer->DoClear({}, depth_float, 0); } else if (surface->type == SurfaceType::DepthStencil) { u32 value_32bit; std::memcpy(&value_32bit, fill_data, sizeof(u32)); @@ -283,7 +284,7 @@ bool RasterizerCache::FillSurface(const Surface& surface, const u8* fill_data, C float depth_float = (value_32bit & 0xFFFFFF) / 16777215.0f; // 2^24 - 1 u8 stencil_int = (value_32bit >> 24); - framebuffer->DoClear(fill_rect, {}, depth_float, stencil_int); + framebuffer->DoClear({}, depth_float, stencil_int); } return true; } @@ -1165,10 +1166,9 @@ const CachedTextureCube& RasterizerCache::GetTextureCube(const TextureCubeConfig return cube; } -SurfaceSurfaceRect_Tuple RasterizerCache::GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, - const Common::Rectangle& viewport_rect) { - const auto& regs = Pica::g_state.regs; - const auto& config = regs.framebuffer.framebuffer; +FramebufferHandle RasterizerCache::GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, + Common::Rectangle viewport_rect) { + const auto& config = Pica::g_state.regs.framebuffer.framebuffer; // update resolution_scale_factor and reset cache if changed /*const bool scale_factor_changed = resolution_scale_factor != VideoCore::GetResolutionScaleFactor(); @@ -1181,14 +1181,14 @@ SurfaceSurfaceRect_Tuple RasterizerCache::GetFramebufferSurfaces(bool using_colo texture_cube_cache.clear(); }*/ - Common::Rectangle viewport_clamped{ + Common::Rectangle viewport_clamped = { static_cast(std::clamp(viewport_rect.left, 0, static_cast(config.GetWidth()))), static_cast(std::clamp(viewport_rect.top, 0, static_cast(config.GetHeight()))), static_cast(std::clamp(viewport_rect.right, 0, static_cast(config.GetWidth()))), - static_cast( - std::clamp(viewport_rect.bottom, 0, static_cast(config.GetHeight())))}; + static_cast(std::clamp(viewport_rect.bottom, 0, static_cast(config.GetHeight()))) + }; - // get color and depth surfaces + // Get color and depth surfaces SurfaceParams color_params; color_params.is_tiled = true; color_params.res_scale = resolution_scale_factor; @@ -1210,22 +1210,22 @@ SurfaceSurfaceRect_Tuple RasterizerCache::GetFramebufferSurfaces(bool using_colo // Make sure that framebuffers don't overlap if both color and depth are being used if (using_color_fb && using_depth_fb && boost::icl::length(color_vp_interval & depth_vp_interval)) { - LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; " + LOG_CRITICAL(Render_Vulkan, "Color and depth framebuffer memory regions overlap; " "overlapping framebuffers not supported!"); using_depth_fb = false; } Common::Rectangle color_rect{}; Surface color_surface = nullptr; - if (using_color_fb) - std::tie(color_surface, color_rect) = - GetSurfaceSubRect(color_params, ScaleMatch::Exact, false); + if (using_color_fb) { + std::tie(color_surface, color_rect) = GetSurfaceSubRect(color_params, ScaleMatch::Exact, false); + } Common::Rectangle depth_rect{}; Surface depth_surface = nullptr; - if (using_depth_fb) - std::tie(depth_surface, depth_rect) = - GetSurfaceSubRect(depth_params, ScaleMatch::Exact, false); + if (using_depth_fb) { + std::tie(depth_surface, depth_rect) = GetSurfaceSubRect(depth_params, ScaleMatch::Exact, false); + } Common::Rectangle fb_rect{}; if (color_surface != nullptr && depth_surface != nullptr) { @@ -1243,18 +1243,35 @@ SurfaceSurfaceRect_Tuple RasterizerCache::GetFramebufferSurfaces(bool using_colo fb_rect = depth_rect; } + // Validate surfaces before the renderer uses them if (color_surface != nullptr) { ValidateSurface(color_surface, boost::icl::first(color_vp_interval), boost::icl::length(color_vp_interval)); color_surface->InvalidateAllWatcher(); } + if (depth_surface != nullptr) { ValidateSurface(depth_surface, boost::icl::first(depth_vp_interval), boost::icl::length(depth_vp_interval)); depth_surface->InvalidateAllWatcher(); } - return std::make_tuple(color_surface, depth_surface, fb_rect); + const FramebufferInfo framebuffer_info = { + .color = using_color_fb ? color_surface->texture : TextureHandle{}, + .depth_stencil = using_depth_fb ? depth_surface->texture : TextureHandle{} + }; + + // Search the framebuffer cache, otherwise create new framebuffer + FramebufferHandle framebuffer; + if (auto iter = framebuffer_cache.find(framebuffer_info); iter != framebuffer_cache.end()) { + framebuffer = iter->second; + } else { + framebuffer = backend->CreateFramebuffer(framebuffer_info); + framebuffer_cache.emplace(framebuffer_info, framebuffer); + } + + framebuffer->SetDrawRect(fb_rect); + return framebuffer; } Surface RasterizerCache::GetFillSurface(const GPU::Regs::MemoryFillConfig& config) { diff --git a/src/video_core/common/rasterizer_cache.h b/src/video_core/common/rasterizer_cache.h index 83a452690..3d96be5c9 100644 --- a/src/video_core/common/rasterizer_cache.h +++ b/src/video_core/common/rasterizer_cache.h @@ -233,8 +233,8 @@ public: const CachedTextureCube& GetTextureCube(const TextureCubeConfig& config); // Get the color and depth surfaces based on the framebuffer configuration - SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, - const Common::Rectangle& viewport_rect); + FramebufferHandle GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, + Common::Rectangle viewport_rect); // Get a surface that matches the fill config Surface GetFillSurface(const GPU::Regs::MemoryFillConfig& config); diff --git a/src/video_core/renderer_vulkan/vk_framebuffer.cpp b/src/video_core/renderer_vulkan/vk_framebuffer.cpp index 76d4b0393..ec6c97571 100644 --- a/src/video_core/renderer_vulkan/vk_framebuffer.cpp +++ b/src/video_core/renderer_vulkan/vk_framebuffer.cpp @@ -57,7 +57,7 @@ Framebuffer::~Framebuffer() { device.destroyFramebuffer(framebuffer); } -void Framebuffer::DoClear(Common::Rectangle rect, Common::Vec4f color, float depth, u8 stencil) { +void Framebuffer::DoClear(Common::Vec4f color, float depth, u8 stencil) { vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer(); u32 clear_value_count = 0; @@ -84,7 +84,7 @@ void Framebuffer::DoClear(Common::Rectangle rect, Common::Vec4f color, floa const vk::RenderPassBeginInfo begin_info = { .renderPass = clear_renderpass, .framebuffer = framebuffer, - .renderArea = ToVkRect2D(rect), + .renderArea = ToVkRect2D(draw_rect), .clearValueCount = clear_value_count, .pClearValues = clear_values.data() }; diff --git a/src/video_core/renderer_vulkan/vk_framebuffer.h b/src/video_core/renderer_vulkan/vk_framebuffer.h index 3151f014a..c2a6fc1c1 100644 --- a/src/video_core/renderer_vulkan/vk_framebuffer.h +++ b/src/video_core/renderer_vulkan/vk_framebuffer.h @@ -18,7 +18,7 @@ public: vk::RenderPass load_renderpass, vk::RenderPass clear_renderpass); ~Framebuffer() override; - void DoClear(Common::Rectangle rect, Common::Vec4f color, float depth, u8 stencil) override; + void DoClear(Common::Vec4f color, float depth, u8 stencil) override; vk::Framebuffer GetHandle() const { return framebuffer;