rasterizer_cache: Return a framebuffer handle from GetFramebufferSurfaces

This commit is contained in:
emufan4568
2022-08-08 14:48:55 +03:00
parent 2d4f762db1
commit 39ca721cac
5 changed files with 53 additions and 30 deletions

View File

@@ -44,24 +44,30 @@ public:
FramebufferBase& operator=(const FramebufferBase&) = delete; FramebufferBase& operator=(const FramebufferBase&) = delete;
// Clears the attachments bound to the framebuffer // Clears the attachments bound to the framebuffer
virtual void DoClear(Common::Rectangle<u32> 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 // Returns an immutable reference to the color attachment
const TextureHandle& GetColorAttachment() const { TextureHandle GetColorAttachment() const {
return info.color; return info.color;
} }
/// Returns an immutable reference to the depth/stencil attachment // Returns an immutable reference to the depth/stencil attachment
const TextureHandle& GetDepthStencilAttachment() const { TextureHandle GetDepthStencilAttachment() const {
return info.depth_stencil; 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 { MSAASamples GetMSAASamples() const {
return info.samples; return info.samples;
} }
protected: protected:
Rect2D draw_rect;
FramebufferInfo info; FramebufferInfo info;
}; };

View File

@@ -252,6 +252,7 @@ bool RasterizerCache::FillSurface(const Surface& surface, const u8* fill_data, C
framebuffer_cache.emplace(framebuffer_info, framebuffer); framebuffer_cache.emplace(framebuffer_info, framebuffer);
} }
framebuffer->SetDrawRect(fill_rect);
surface->InvalidateAllWatcher(); surface->InvalidateAllWatcher();
if (surface->type == SurfaceType::Color || surface->type == SurfaceType::Texture) { 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<Pica::TexturingRegs::TextureFormat>(surface->pixel_format); tex_info.format = static_cast<Pica::TexturingRegs::TextureFormat>(surface->pixel_format);
Common::Vec4f color_values = Pica::Texture::LookupTexture(fill_data, 0, 0, tex_info) / 255.f; 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) { } else if (surface->type == SurfaceType::Depth) {
u32 depth_32bit = 0; u32 depth_32bit = 0;
float depth_float; float depth_float;
@@ -275,7 +276,7 @@ bool RasterizerCache::FillSurface(const Surface& surface, const u8* fill_data, C
UNREACHABLE(); UNREACHABLE();
} }
framebuffer->DoClear(fill_rect, {}, depth_float, 0); framebuffer->DoClear({}, depth_float, 0);
} else if (surface->type == SurfaceType::DepthStencil) { } else if (surface->type == SurfaceType::DepthStencil) {
u32 value_32bit; u32 value_32bit;
std::memcpy(&value_32bit, fill_data, sizeof(u32)); 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 float depth_float = (value_32bit & 0xFFFFFF) / 16777215.0f; // 2^24 - 1
u8 stencil_int = (value_32bit >> 24); u8 stencil_int = (value_32bit >> 24);
framebuffer->DoClear(fill_rect, {}, depth_float, stencil_int); framebuffer->DoClear({}, depth_float, stencil_int);
} }
return true; return true;
} }
@@ -1165,10 +1166,9 @@ const CachedTextureCube& RasterizerCache::GetTextureCube(const TextureCubeConfig
return cube; return cube;
} }
SurfaceSurfaceRect_Tuple RasterizerCache::GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, FramebufferHandle RasterizerCache::GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb,
const Common::Rectangle<s32>& viewport_rect) { Common::Rectangle<s32> viewport_rect) {
const auto& regs = Pica::g_state.regs; const auto& config = Pica::g_state.regs.framebuffer.framebuffer;
const auto& config = regs.framebuffer.framebuffer;
// update resolution_scale_factor and reset cache if changed // update resolution_scale_factor and reset cache if changed
/*const bool scale_factor_changed = resolution_scale_factor != VideoCore::GetResolutionScaleFactor(); /*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(); texture_cube_cache.clear();
}*/ }*/
Common::Rectangle<u32> viewport_clamped{ Common::Rectangle<u32> viewport_clamped = {
static_cast<u32>(std::clamp(viewport_rect.left, 0, static_cast<s32>(config.GetWidth()))), static_cast<u32>(std::clamp(viewport_rect.left, 0, static_cast<s32>(config.GetWidth()))),
static_cast<u32>(std::clamp(viewport_rect.top, 0, static_cast<s32>(config.GetHeight()))), static_cast<u32>(std::clamp(viewport_rect.top, 0, static_cast<s32>(config.GetHeight()))),
static_cast<u32>(std::clamp(viewport_rect.right, 0, static_cast<s32>(config.GetWidth()))), static_cast<u32>(std::clamp(viewport_rect.right, 0, static_cast<s32>(config.GetWidth()))),
static_cast<u32>( static_cast<u32>(std::clamp(viewport_rect.bottom, 0, static_cast<s32>(config.GetHeight())))
std::clamp(viewport_rect.bottom, 0, static_cast<s32>(config.GetHeight())))}; };
// get color and depth surfaces // Get color and depth surfaces
SurfaceParams color_params; SurfaceParams color_params;
color_params.is_tiled = true; color_params.is_tiled = true;
color_params.res_scale = resolution_scale_factor; 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 // Make sure that framebuffers don't overlap if both color and depth are being used
if (using_color_fb && using_depth_fb && if (using_color_fb && using_depth_fb &&
boost::icl::length(color_vp_interval & depth_vp_interval)) { 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!"); "overlapping framebuffers not supported!");
using_depth_fb = false; using_depth_fb = false;
} }
Common::Rectangle<u32> color_rect{}; Common::Rectangle<u32> color_rect{};
Surface color_surface = nullptr; Surface color_surface = nullptr;
if (using_color_fb) if (using_color_fb) {
std::tie(color_surface, color_rect) = std::tie(color_surface, color_rect) = GetSurfaceSubRect(color_params, ScaleMatch::Exact, false);
GetSurfaceSubRect(color_params, ScaleMatch::Exact, false); }
Common::Rectangle<u32> depth_rect{}; Common::Rectangle<u32> depth_rect{};
Surface depth_surface = nullptr; Surface depth_surface = nullptr;
if (using_depth_fb) if (using_depth_fb) {
std::tie(depth_surface, depth_rect) = std::tie(depth_surface, depth_rect) = GetSurfaceSubRect(depth_params, ScaleMatch::Exact, false);
GetSurfaceSubRect(depth_params, ScaleMatch::Exact, false); }
Common::Rectangle<u32> fb_rect{}; Common::Rectangle<u32> fb_rect{};
if (color_surface != nullptr && depth_surface != nullptr) { if (color_surface != nullptr && depth_surface != nullptr) {
@@ -1243,18 +1243,35 @@ SurfaceSurfaceRect_Tuple RasterizerCache::GetFramebufferSurfaces(bool using_colo
fb_rect = depth_rect; fb_rect = depth_rect;
} }
// Validate surfaces before the renderer uses them
if (color_surface != nullptr) { if (color_surface != nullptr) {
ValidateSurface(color_surface, boost::icl::first(color_vp_interval), ValidateSurface(color_surface, boost::icl::first(color_vp_interval),
boost::icl::length(color_vp_interval)); boost::icl::length(color_vp_interval));
color_surface->InvalidateAllWatcher(); color_surface->InvalidateAllWatcher();
} }
if (depth_surface != nullptr) { if (depth_surface != nullptr) {
ValidateSurface(depth_surface, boost::icl::first(depth_vp_interval), ValidateSurface(depth_surface, boost::icl::first(depth_vp_interval),
boost::icl::length(depth_vp_interval)); boost::icl::length(depth_vp_interval));
depth_surface->InvalidateAllWatcher(); 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) { Surface RasterizerCache::GetFillSurface(const GPU::Regs::MemoryFillConfig& config) {

View File

@@ -233,8 +233,8 @@ public:
const CachedTextureCube& GetTextureCube(const TextureCubeConfig& config); const CachedTextureCube& GetTextureCube(const TextureCubeConfig& config);
// Get the color and depth surfaces based on the framebuffer configuration // Get the color and depth surfaces based on the framebuffer configuration
SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, FramebufferHandle GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb,
const Common::Rectangle<s32>& viewport_rect); Common::Rectangle<s32> viewport_rect);
// Get a surface that matches the fill config // Get a surface that matches the fill config
Surface GetFillSurface(const GPU::Regs::MemoryFillConfig& config); Surface GetFillSurface(const GPU::Regs::MemoryFillConfig& config);

View File

@@ -57,7 +57,7 @@ Framebuffer::~Framebuffer() {
device.destroyFramebuffer(framebuffer); device.destroyFramebuffer(framebuffer);
} }
void Framebuffer::DoClear(Common::Rectangle<u32> rect, Common::Vec4f color, float depth, u8 stencil) { void Framebuffer::DoClear(Common::Vec4f color, float depth, u8 stencil) {
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer(); vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
u32 clear_value_count = 0; u32 clear_value_count = 0;
@@ -84,7 +84,7 @@ void Framebuffer::DoClear(Common::Rectangle<u32> rect, Common::Vec4f color, floa
const vk::RenderPassBeginInfo begin_info = { const vk::RenderPassBeginInfo begin_info = {
.renderPass = clear_renderpass, .renderPass = clear_renderpass,
.framebuffer = framebuffer, .framebuffer = framebuffer,
.renderArea = ToVkRect2D(rect), .renderArea = ToVkRect2D(draw_rect),
.clearValueCount = clear_value_count, .clearValueCount = clear_value_count,
.pClearValues = clear_values.data() .pClearValues = clear_values.data()
}; };

View File

@@ -18,7 +18,7 @@ public:
vk::RenderPass load_renderpass, vk::RenderPass clear_renderpass); vk::RenderPass load_renderpass, vk::RenderPass clear_renderpass);
~Framebuffer() override; ~Framebuffer() override;
void DoClear(Common::Rectangle<u32> rect, Common::Vec4f color, float depth, u8 stencil) override; void DoClear(Common::Vec4f color, float depth, u8 stencil) override;
vk::Framebuffer GetHandle() const { vk::Framebuffer GetHandle() const {
return framebuffer; return framebuffer;