diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 919931d640..59f1a89c9e 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -29,29 +29,37 @@ struct FormatTuple { bool compressed; }; -SurfaceParams::SurfaceParams(const Tegra::Texture::FullTextureInfo& config) - : addr(config.tic.Address()), is_tiled(config.tic.IsTiled()), - block_height(is_tiled ? config.tic.BlockHeight() : 0), - pixel_format(PixelFormatFromTextureFormat(config.tic.format)), - component_type(ComponentTypeFromTexture(config.tic.r_type.Value())), - type(GetFormatType(pixel_format)), - width(Common::AlignUp(config.tic.Width(), GetCompressionFactor(pixel_format))), - height(Common::AlignUp(config.tic.Height(), GetCompressionFactor(pixel_format))), - size_in_bytes(SizeInBytes()) { +/*static*/ SurfaceParams SurfaceParams::CreateForTexture( + const Tegra::Texture::FullTextureInfo& config) { - // TODO(Subv): Different types per component are not supported. - ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() && - config.tic.r_type.Value() == config.tic.b_type.Value() && - config.tic.r_type.Value() == config.tic.a_type.Value()); + SurfaceParams params{}; + params.addr = config.tic.Address(); + params.is_tiled = config.tic.IsTiled(); + params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0, + params.pixel_format = PixelFormatFromTextureFormat(config.tic.format); + params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value()); + params.type = GetFormatType(params.pixel_format); + params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); + params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format)); + params.size_in_bytes = params.SizeInBytes(); + return params; } -SurfaceParams::SurfaceParams(const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config) - : addr(config.Address()), is_tiled(true), - block_height(Tegra::Texture::TICEntry::DefaultBlockHeight), - pixel_format(PixelFormatFromRenderTargetFormat(config.format)), - component_type(ComponentTypeFromRenderTarget(config.format)), - type(GetFormatType(pixel_format)), width(config.width), height(config.height), - size_in_bytes(SizeInBytes()) {} +/*static*/ SurfaceParams SurfaceParams::CreateForFramebuffer( + const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config) { + + SurfaceParams params{}; + params.addr = config.Address(); + params.is_tiled = true; + params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight; + params.pixel_format = PixelFormatFromRenderTargetFormat(config.format); + params.component_type = ComponentTypeFromRenderTarget(config.format); + params.type = GetFormatType(params.pixel_format); + params.width = config.width; + params.height = config.height; + params.size_in_bytes = params.SizeInBytes(); + return params; +} static constexpr std::array tex_format_tuples = {{ {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false}, // ABGR8 @@ -358,7 +366,7 @@ RasterizerCacheOpenGL::RasterizerCacheOpenGL() { } Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextureInfo& config) { - return GetSurface(SurfaceParams(config)); + return GetSurface(SurfaceParams::CreateForTexture(config)); } SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( @@ -369,8 +377,8 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( NGLOG_WARNING(Render_OpenGL, "hard-coded for render target 0!"); // get color and depth surfaces - SurfaceParams color_params(regs.rt[0]); - SurfaceParams depth_params = color_params; + const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(regs.rt[0])}; + const SurfaceParams depth_params{color_params}; ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented"); @@ -423,13 +431,14 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { } // Check for an exact match in existing surfaces - auto search = surface_cache.find(params.addr); + const auto& surface_key{SurfaceKey::Create(params)}; + const auto& search{surface_cache.find(surface_key)}; Surface surface; if (search != surface_cache.end()) { surface = search->second; } else { surface = std::make_shared(params); - surface_cache[params.addr] = surface; + surface_cache[surface_key] = surface; } LoadSurface(surface); @@ -439,10 +448,10 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params) { Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr cpu_addr) const { // Tries to find the GPU address of a framebuffer based on the CPU address. This is because - // final output framebuffers are specified by CPU address, but internally our GPU cache uses GPU - // addresses. We iterate through all cached framebuffers, and compare their starting CPU address - // to the one provided. This is obviously not great, and won't work if the framebuffer overlaps - // surfaces. + // final output framebuffers are specified by CPU address, but internally our GPU cache uses + // GPU addresses. We iterate through all cached framebuffers, and compare their starting CPU + // address to the one provided. This is obviously not great, and won't work if the + // framebuffer overlaps surfaces. std::vector surfaces; for (const auto& surface : surface_cache) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 53ff2722d2..bf36f6c249 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -9,6 +9,7 @@ #include #include "common/common_types.h" +#include "common/hash.h" #include "common/math_util.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/renderer_opengl/gl_resource_manager.h" @@ -253,22 +254,41 @@ struct SurfaceParams { GetFormatBpp(pixel_format) / CHAR_BIT; } - SurfaceParams(const Tegra::Texture::FullTextureInfo& config); - SurfaceParams(const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config); - VAddr GetCpuAddr() const; - const Tegra::GPUVAddr addr; - const bool is_tiled; - const u32 block_height; - const PixelFormat pixel_format; - const ComponentType component_type; - const SurfaceType type; - const u32 width; - const u32 height; - const size_t size_in_bytes; + static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config); + + static SurfaceParams CreateForFramebuffer( + const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config); + + Tegra::GPUVAddr addr; + bool is_tiled; + u32 block_height; + PixelFormat pixel_format; + ComponentType component_type; + SurfaceType type; + u32 width; + u32 height; + size_t size_in_bytes; }; +struct SurfaceKey : Common::HashableStruct { + static SurfaceKey Create(const SurfaceParams& params) { + SurfaceKey res; + res.state = params; + return res; + } +}; + +namespace std { +template <> +struct hash { + size_t operator()(const SurfaceKey& k) const { + return k.Hash(); + } +}; +} // namespace std + class CachedSurface final { public: CachedSurface(const SurfaceParams& params); @@ -317,7 +337,7 @@ public: private: Surface GetSurface(const SurfaceParams& params); - std::map surface_cache; + std::unordered_map surface_cache; OGLFramebuffer read_framebuffer; OGLFramebuffer draw_framebuffer; };