From 7f1aec8fbb96b5c29c91332250eef60dff4c8f12 Mon Sep 17 00:00:00 2001 From: Phantom Date: Sat, 30 Dec 2017 07:42:32 +0100 Subject: [PATCH] Support for textures smaller than 8*8 --- .../renderer_opengl/gl_rasterizer_cache.cpp | 89 +++++++++++-------- .../renderer_opengl/gl_rasterizer_cache.h | 1 + 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index aa3009b5b..066a58085 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -449,27 +449,18 @@ MathUtil::Rectangle SurfaceParams::GetScaledSubRect(const SurfaceParams& su bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { return (other_surface.addr == addr && other_surface.width == width && other_surface.height == height && other_surface.stride == stride && - other_surface.pixel_format == pixel_format && other_surface.is_tiled == is_tiled); + other_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid && + other_surface.is_tiled == is_tiled); } bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { - if (sub_surface.addr < addr || sub_surface.end > end || sub_surface.stride != stride || - sub_surface.pixel_format != pixel_format || sub_surface.is_tiled != is_tiled || - (sub_surface.addr - addr) * 8 % GetFormatBpp() != 0) - return false; - - auto rect = GetSubRect(sub_surface); - - if (rect.left + sub_surface.width > stride) { - return false; - } - - if (is_tiled) { - return PixelsInBytes(sub_surface.addr - addr) % 64 == 0 && sub_surface.height % 8 == 0 && - sub_surface.width % 8 == 0; - } - - return true; + return (sub_surface.addr >= addr && sub_surface.end <= end && + sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid && + sub_surface.is_tiled == is_tiled && + (sub_surface.addr - addr) * 8 % GetFormatBpp() == 0 && + (!is_tiled || PixelsInBytes(sub_surface.addr - addr) % 64 == 0) && + (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) && + GetSubRect(sub_surface).left + sub_surface.width <= stride); } bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const { @@ -1006,15 +997,6 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc if (expandable != nullptr && expandable->res_scale > target_res_scale) { target_res_scale = expandable->res_scale; } - // Keep res_scale when reinterpreting d24s8 -> rgba8 - if (params.pixel_format == PixelFormat::RGBA8) { - find_params.pixel_format = PixelFormat::D24S8; - expandable = FindMatch( - surface_cache, find_params, match_res_scale); - if (expandable != nullptr && expandable->res_scale > target_res_scale) { - target_res_scale = expandable->res_scale; - } - } } SurfaceParams new_params = params; new_params.res_scale = target_res_scale; @@ -1057,17 +1039,29 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& } } + SurfaceParams aligned_params = params; + if (params.is_tiled) { + aligned_params.height = Common::AlignUp(params.height, 8); + aligned_params.width = Common::AlignUp(params.width, 8); + aligned_params.stride = Common::AlignUp(params.stride, 8); + aligned_params.UpdateParams(); + } + // Check for a surface we can expand before creating a new one if (surface == nullptr) { - surface = FindMatch(surface_cache, params, + surface = FindMatch(surface_cache, aligned_params, match_res_scale); if (surface != nullptr) { + aligned_params.width = aligned_params.stride; + aligned_params.UpdateParams(); + SurfaceParams new_params = *surface; - new_params.addr = std::min(params.addr, surface->addr); - new_params.end = std::max(params.end, surface->end); + new_params.addr = std::min(aligned_params.addr, surface->addr); + new_params.end = std::max(aligned_params.end, surface->end); new_params.size = new_params.end - new_params.addr; - new_params.height = new_params.size / params.BytesInPixels(params.stride); - ASSERT(new_params.size % params.BytesInPixels(params.stride) == 0); + new_params.height = + new_params.size / aligned_params.BytesInPixels(aligned_params.stride); + ASSERT(new_params.size % aligned_params.BytesInPixels(aligned_params.stride) == 0); Surface new_surface = CreateSurface(new_params); DuplicateSurface(surface, new_surface); @@ -1083,14 +1077,14 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& // No subrect found - create and return a new surface if (surface == nullptr) { - SurfaceParams new_params = params; + SurfaceParams new_params = aligned_params; // Can't have gaps in a surface - new_params.width = params.stride; + new_params.width = aligned_params.stride; new_params.UpdateParams(); // GetSurface will create the new surface and possibly adjust res_scale if necessary surface = GetSurface(new_params, match_res_scale, load_if_create); } else if (load_if_create) { - ValidateSurface(surface, params.addr, params.size); + ValidateSurface(surface, aligned_params.addr, aligned_params.size); } return std::make_tuple(surface, surface->GetScaledSubRect(params)); @@ -1108,6 +1102,23 @@ Surface RasterizerCacheOpenGL::GetTextureSurface( params.is_tiled = true; params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(info.format); params.UpdateParams(); + + if (info.width % 8 != 0 || info.height % 8 != 0) { + Surface src_surface; + MathUtil::Rectangle rect; + std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); + + params.res_scale = src_surface->res_scale; + Surface tmp_surface = CreateSurface(params); + BlitTextures(src_surface->texture.handle, rect, tmp_surface->texture.handle, + tmp_surface->GetScaledRect(), + SurfaceParams::GetFormatType(params.pixel_format), read_framebuffer.handle, + draw_framebuffer.handle); + + remove_surfaces.emplace(tmp_surface); + return tmp_surface; + } + return GetSurface(params, ScaleMatch::Ignore, true); } @@ -1422,11 +1433,19 @@ Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) { } void RasterizerCacheOpenGL::RegisterSurface(const Surface& surface) { + if (surface->registered) { + return; + } + surface->registered = true; surface_cache.add({surface->GetInterval(), SurfaceSet{surface}}); UpdatePagesCachedCount(surface->addr, surface->size, 1); } void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) { + if (!surface->registered) { + return; + } + surface->registered = false; UpdatePagesCachedCount(surface->addr, surface->size, -1); surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}}); } diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index deb091317..d1f739a78 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -265,6 +265,7 @@ struct CachedSurface : SurfaceParams { return (invalid_regions & GetInterval()) == SurfaceRegions(GetInterval()); } + bool registered = false; SurfaceRegions invalid_regions; u32 fill_size = 0; /// Number of bytes to read from fill_data