diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 1bb842fe79..24781a3c10 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -34,16 +34,29 @@ struct FormatTuple {
     bool compressed;
 };
 
-static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
-    auto& gpu{Core::System::GetInstance().GPU()};
-    const auto cpu_addr{gpu.MemoryManager().GpuToCpuAddress(gpu_addr)};
-    return cpu_addr ? *cpu_addr : 0;
+void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr) {
+    auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()};
+    const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr)};
+    const auto max_size{memory_manager.GetRegionEnd(gpu_addr) - gpu_addr};
+
+    addr = cpu_addr ? *cpu_addr : 0;
+    size_in_bytes_total = SizeInBytesTotal();
+    size_in_bytes_2d = SizeInBytes2D();
+
+    // Clamp sizes to mapped GPU memory region
+    if (size_in_bytes_2d > max_size) {
+        LOG_ERROR(HW_GPU, "Surface size {} exceeds region size {}", size_in_bytes_2d, max_size);
+        size_in_bytes_total = max_size;
+        size_in_bytes_2d = max_size;
+    } else if (size_in_bytes_total > max_size) {
+        LOG_ERROR(HW_GPU, "Surface size {} exceeds region size {}", size_in_bytes_total, max_size);
+        size_in_bytes_total = max_size;
+    }
 }
 
 /*static*/ SurfaceParams SurfaceParams::CreateForTexture(
     const Tegra::Texture::FullTextureInfo& config, const GLShader::SamplerEntry& entry) {
     SurfaceParams params{};
-    params.addr = TryGetCpuAddr(config.tic.Address());
     params.is_tiled = config.tic.IsTiled();
     params.block_width = params.is_tiled ? config.tic.BlockWidth() : 0,
     params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0,
@@ -87,18 +100,18 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
         break;
     }
 
-    params.size_in_bytes_total = params.SizeInBytesTotal();
-    params.size_in_bytes_2d = params.SizeInBytes2D();
     params.max_mip_level = config.tic.max_mip_level + 1;
     params.rt = {};
 
+    params.InitCacheParameters(config.tic.Address());
+
     return params;
 }
 
 /*static*/ SurfaceParams SurfaceParams::CreateForFramebuffer(std::size_t index) {
     const auto& config{Core::System::GetInstance().GPU().Maxwell3D().regs.rt[index]};
     SurfaceParams params{};
-    params.addr = TryGetCpuAddr(config.Address());
+
     params.is_tiled =
         config.memory_layout.type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear;
     params.block_width = 1 << config.memory_layout.block_width;
@@ -112,8 +125,6 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
     params.unaligned_height = config.height;
     params.target = SurfaceTarget::Texture2D;
     params.depth = 1;
-    params.size_in_bytes_total = params.SizeInBytesTotal();
-    params.size_in_bytes_2d = params.SizeInBytes2D();
     params.max_mip_level = 0;
 
     // Render target specific parameters, not used for caching
@@ -122,6 +133,8 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
     params.rt.layer_stride = config.layer_stride;
     params.rt.base_layer = config.base_layer;
 
+    params.InitCacheParameters(config.Address());
+
     return params;
 }
 
@@ -130,7 +143,7 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
     u32 block_width, u32 block_height, u32 block_depth,
     Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout type) {
     SurfaceParams params{};
-    params.addr = TryGetCpuAddr(zeta_address);
+
     params.is_tiled = type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear;
     params.block_width = 1 << std::min(block_width, 5U);
     params.block_height = 1 << std::min(block_height, 5U);
@@ -143,18 +156,18 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
     params.unaligned_height = zeta_height;
     params.target = SurfaceTarget::Texture2D;
     params.depth = 1;
-    params.size_in_bytes_total = params.SizeInBytesTotal();
-    params.size_in_bytes_2d = params.SizeInBytes2D();
     params.max_mip_level = 0;
     params.rt = {};
 
+    params.InitCacheParameters(zeta_address);
+
     return params;
 }
 
 /*static*/ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
     const Tegra::Engines::Fermi2D::Regs::Surface& config) {
     SurfaceParams params{};
-    params.addr = TryGetCpuAddr(config.Address());
+
     params.is_tiled = !config.linear;
     params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 32U) : 0,
     params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 32U) : 0,
@@ -167,11 +180,11 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
     params.unaligned_height = config.height;
     params.target = SurfaceTarget::Texture2D;
     params.depth = 1;
-    params.size_in_bytes_total = params.SizeInBytesTotal();
-    params.size_in_bytes_2d = params.SizeInBytes2D();
     params.max_mip_level = 0;
     params.rt = {};
 
+    params.InitCacheParameters(config.Address());
+
     return params;
 }
 
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index a15fb7b072..f6f7aad82a 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -742,7 +742,9 @@ struct SurfaceParams {
                         other.depth);
     }
 
-    VAddr addr;
+    /// Initializes parameters for caching, should be called after everything has been initialized
+    void InitCacheParameters(Tegra::GPUVAddr gpu_addr);
+
     bool is_tiled;
     u32 block_width;
     u32 block_height;
@@ -754,11 +756,14 @@ struct SurfaceParams {
     u32 height;
     u32 depth;
     u32 unaligned_height;
-    std::size_t size_in_bytes_total;
-    std::size_t size_in_bytes_2d;
     SurfaceTarget target;
     u32 max_mip_level;
 
+    // Parameters used for caching
+    VAddr addr;
+    std::size_t size_in_bytes_total;
+    std::size_t size_in_bytes_2d;
+
     // Render target specific parameters, not used in caching
     struct {
         u32 index;