summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-04-16 20:01:07 -0300
committerGravatar ReinUsesLisp2019-06-20 21:36:11 -0300
commit4b396f375c0d32b60595f224d06b1b63d6df6b0a (patch)
treed61b116481b20802deee2472735e83c053901454 /src
parentgl_texture_cache: Add copy from multiple overlaps into a single surface (diff)
downloadyuzu-4b396f375c0d32b60595f224d06b1b63d6df6b0a.tar.gz
yuzu-4b396f375c0d32b60595f224d06b1b63d6df6b0a.tar.xz
yuzu-4b396f375c0d32b60595f224d06b1b63d6df6b0a.zip
gl_texture_cache: Minor changes
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp50
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h20
-rw-r--r--src/video_core/texture_cache.cpp72
-rw-r--r--src/video_core/texture_cache.h175
5 files changed, 185 insertions, 140 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 07c28357e..af63365a4 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -498,8 +498,8 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
498 color_surface->MarkAsModified(true); 498 color_surface->MarkAsModified(true);
499 // Workaround for and issue in nvidia drivers 499 // Workaround for and issue in nvidia drivers
500 // https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/ 500 // https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/
501 // state.framebuffer_srgb.enabled |= 501 state.framebuffer_srgb.enabled |=
502 // color_surface->GetSurfaceParams().srgb_conversion; 502 color_surface->GetSurfaceParams().GetSrgbConversion();
503 } 503 }
504 504
505 fbkey.is_single_buffer = true; 505 fbkey.is_single_buffer = true;
@@ -519,8 +519,8 @@ std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
519 // Enable sRGB only for supported formats 519 // Enable sRGB only for supported formats
520 // Workaround for and issue in nvidia drivers 520 // Workaround for and issue in nvidia drivers
521 // https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/ 521 // https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/
522 // state.framebuffer_srgb.enabled |= 522 state.framebuffer_srgb.enabled |=
523 // color_surface->GetSurfaceParams().srgb_conversion; 523 color_surface->GetSurfaceParams().GetSrgbConversion();
524 } 524 }
525 525
526 fbkey.color_attachments[index] = 526 fbkey.color_attachments[index] =
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 6a6fe7cc4..da2d1e63a 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -8,6 +8,7 @@
8#include "video_core/morton.h" 8#include "video_core/morton.h"
9#include "video_core/renderer_opengl/gl_resource_manager.h" 9#include "video_core/renderer_opengl/gl_resource_manager.h"
10#include "video_core/renderer_opengl/gl_texture_cache.h" 10#include "video_core/renderer_opengl/gl_texture_cache.h"
11#include "video_core/renderer_opengl/utils.h"
11#include "video_core/texture_cache.h" 12#include "video_core/texture_cache.h"
12#include "video_core/textures/convert.h" 13#include "video_core/textures/convert.h"
13#include "video_core/textures/texture.h" 14#include "video_core/textures/texture.h"
@@ -285,6 +286,8 @@ void CachedSurface::LoadBuffer() {
285} 286}
286 287
287void CachedSurface::FlushBufferImpl() { 288void CachedSurface::FlushBufferImpl() {
289 LOG_CRITICAL(Render_OpenGL, "Flushing");
290
288 if (!IsModified()) { 291 if (!IsModified()) {
289 return; 292 return;
290 } 293 }
@@ -352,9 +355,6 @@ void CachedSurface::UploadTextureMipmap(u32 level) {
352 355
353 if (is_compressed) { 356 if (is_compressed) {
354 const auto image_size{static_cast<GLsizei>(params.GetHostMipmapSize(level))}; 357 const auto image_size{static_cast<GLsizei>(params.GetHostMipmapSize(level))};
355 GLint expected_size;
356 glGetTextureLevelParameteriv(texture.handle, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE,
357 &expected_size);
358 switch (params.GetTarget()) { 358 switch (params.GetTarget()) {
359 case SurfaceTarget::Texture2D: 359 case SurfaceTarget::Texture2D:
360 glCompressedTextureSubImage2D(texture.handle, level, 0, 0, 360 glCompressedTextureSubImage2D(texture.handle, level, 0, 0,
@@ -419,6 +419,10 @@ void CachedSurface::UploadTextureMipmap(u32 level) {
419 } 419 }
420} 420}
421 421
422void CachedSurface::DecorateSurfaceName() {
423 LabelGLObject(GL_TEXTURE, texture.handle, GetGpuAddr());
424}
425
422std::unique_ptr<CachedSurfaceView> CachedSurface::CreateView(const ViewKey& view_key) { 426std::unique_ptr<CachedSurfaceView> CachedSurface::CreateView(const ViewKey& view_key) {
423 return std::make_unique<CachedSurfaceView>(*this, view_key); 427 return std::make_unique<CachedSurfaceView>(*this, view_key);
424} 428}
@@ -517,11 +521,13 @@ TextureCacheOpenGL::TextureCacheOpenGL(Core::System& system,
517 521
518TextureCacheOpenGL::~TextureCacheOpenGL() = default; 522TextureCacheOpenGL::~TextureCacheOpenGL() = default;
519 523
520CachedSurfaceView* TextureCacheOpenGL::TryFastGetSurfaceView( 524CachedSurfaceView* TextureCacheOpenGL::TryFastGetSurfaceView(GPUVAddr gpu_addr, VAddr cpu_addr,
521 VAddr cpu_addr, u8* host_ptr, const SurfaceParams& new_params, bool preserve_contents, 525 u8* host_ptr,
522 const std::vector<CachedSurface*>& overlaps) { 526 const SurfaceParams& new_params,
527 bool preserve_contents,
528 const std::vector<Surface>& overlaps) {
523 if (overlaps.size() > 1) { 529 if (overlaps.size() > 1) {
524 return TryCopyAsViews(cpu_addr, host_ptr, new_params, overlaps); 530 return TryCopyAsViews(gpu_addr, cpu_addr, host_ptr, new_params, overlaps);
525 } 531 }
526 532
527 const auto& old_surface{overlaps[0]}; 533 const auto& old_surface{overlaps[0]};
@@ -530,18 +536,18 @@ CachedSurfaceView* TextureCacheOpenGL::TryFastGetSurfaceView(
530 old_params.GetDepth() == new_params.GetDepth() && old_params.GetDepth() == 1 && 536 old_params.GetDepth() == new_params.GetDepth() && old_params.GetDepth() == 1 &&
531 old_params.GetNumLevels() == new_params.GetNumLevels() && 537 old_params.GetNumLevels() == new_params.GetNumLevels() &&
532 old_params.GetPixelFormat() == new_params.GetPixelFormat()) { 538 old_params.GetPixelFormat() == new_params.GetPixelFormat()) {
533 return SurfaceCopy(cpu_addr, host_ptr, new_params, old_surface, old_params); 539 return SurfaceCopy(gpu_addr, cpu_addr, host_ptr, new_params, old_surface, old_params);
534 } 540 }
535 541
536 return nullptr; 542 return nullptr;
537} 543}
538 544
539CachedSurfaceView* TextureCacheOpenGL::SurfaceCopy(VAddr cpu_addr, u8* host_ptr, 545CachedSurfaceView* TextureCacheOpenGL::SurfaceCopy(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
540 const SurfaceParams& new_params, 546 const SurfaceParams& new_params,
541 CachedSurface* old_surface, 547 const Surface& old_surface,
542 const SurfaceParams& old_params) { 548 const SurfaceParams& old_params) {
543 CachedSurface* const new_surface{GetUncachedSurface(new_params)}; 549 const auto new_surface{GetUncachedSurface(new_params)};
544 Register(new_surface, cpu_addr, host_ptr); 550 Register(new_surface, gpu_addr, cpu_addr, host_ptr);
545 551
546 const u32 min_width{ 552 const u32 min_width{
547 std::max(old_params.GetDefaultBlockWidth(), new_params.GetDefaultBlockWidth())}; 553 std::max(old_params.GetDefaultBlockWidth(), new_params.GetDefaultBlockWidth())};
@@ -562,12 +568,12 @@ CachedSurfaceView* TextureCacheOpenGL::SurfaceCopy(VAddr cpu_addr, u8* host_ptr,
562 new_surface->MarkAsModified(true); 568 new_surface->MarkAsModified(true);
563 569
564 // TODO(Rodrigo): Add an entry to directly get the superview 570 // TODO(Rodrigo): Add an entry to directly get the superview
565 return new_surface->GetView(cpu_addr, new_params); 571 return new_surface->GetView(gpu_addr, new_params);
566} 572}
567 573
568CachedSurfaceView* TextureCacheOpenGL::TryCopyAsViews(VAddr cpu_addr, u8* host_ptr, 574CachedSurfaceView* TextureCacheOpenGL::TryCopyAsViews(GPUVAddr gpu_addr, VAddr cpu_addr,
569 const SurfaceParams& new_params, 575 u8* host_ptr, const SurfaceParams& new_params,
570 const std::vector<CachedSurface*>& overlaps) { 576 const std::vector<Surface>& overlaps) {
571 if (new_params.GetTarget() == SurfaceTarget::Texture1D || 577 if (new_params.GetTarget() == SurfaceTarget::Texture1D ||
572 new_params.GetTarget() == SurfaceTarget::Texture1DArray || 578 new_params.GetTarget() == SurfaceTarget::Texture1DArray ||
573 new_params.GetTarget() == SurfaceTarget::Texture3D) { 579 new_params.GetTarget() == SurfaceTarget::Texture3D) {
@@ -575,16 +581,16 @@ CachedSurfaceView* TextureCacheOpenGL::TryCopyAsViews(VAddr cpu_addr, u8* host_p
575 return nullptr; 581 return nullptr;
576 } 582 }
577 583
578 CachedSurface* const new_surface{GetUncachedSurface(new_params)}; 584 const auto new_surface{GetUncachedSurface(new_params)};
579 // TODO(Rodrigo): Move this down 585 // TODO(Rodrigo): Move this down
580 Register(new_surface, cpu_addr, host_ptr); 586 Register(new_surface, gpu_addr, cpu_addr, host_ptr);
581 587
582 // TODO(Rodrigo): Find a way to avoid heap allocations here. 588 // TODO(Rodrigo): Find a way to avoid heap allocations here.
583 std::vector<CachedSurfaceView*> views; 589 std::vector<CachedSurfaceView*> views;
584 views.reserve(overlaps.size()); 590 views.reserve(overlaps.size());
585 for (const auto& overlap : overlaps) { 591 for (const auto& overlap : overlaps) {
586 const auto view{ 592 const auto view{
587 new_surface->TryGetView(overlap->GetCpuAddr(), overlap->GetSurfaceParams())}; 593 new_surface->TryGetView(overlap->GetGpuAddr(), overlap->GetSurfaceParams())};
588 if (!view) { 594 if (!view) {
589 // TODO(Rodrigo): Remove this 595 // TODO(Rodrigo): Remove this
590 Unregister(new_surface); 596 Unregister(new_surface);
@@ -610,11 +616,11 @@ CachedSurfaceView* TextureCacheOpenGL::TryCopyAsViews(VAddr cpu_addr, u8* host_p
610 new_surface->MarkAsModified(true); 616 new_surface->MarkAsModified(true);
611 617
612 // TODO(Rodrigo): Add an entry to directly get the superview 618 // TODO(Rodrigo): Add an entry to directly get the superview
613 return new_surface->GetView(cpu_addr, new_params); 619 return new_surface->GetView(gpu_addr, new_params);
614} 620}
615 621
616std::unique_ptr<CachedSurface> TextureCacheOpenGL::CreateSurface(const SurfaceParams& params) { 622Surface TextureCacheOpenGL::CreateSurface(const SurfaceParams& params) {
617 return std::make_unique<CachedSurface>(params); 623 return std::make_unique<CachedSurface>(*this, params);
618} 624}
619 625
620} // namespace OpenGL 626} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 86ad91dab..8705db74c 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -27,6 +27,7 @@ using VideoCore::Surface::SurfaceType;
27class CachedSurfaceView; 27class CachedSurfaceView;
28class CachedSurface; 28class CachedSurface;
29 29
30using Surface = std::shared_ptr<CachedSurface>;
30using TextureCacheBase = VideoCommon::TextureCacheContextless<CachedSurface, CachedSurfaceView>; 31using TextureCacheBase = VideoCommon::TextureCacheContextless<CachedSurface, CachedSurfaceView>;
31 32
32class CachedSurface final : public VideoCommon::SurfaceBaseContextless<CachedSurfaceView> { 33class CachedSurface final : public VideoCommon::SurfaceBaseContextless<CachedSurfaceView> {
@@ -47,6 +48,8 @@ public:
47 } 48 }
48 49
49protected: 50protected:
51 void DecorateSurfaceName();
52
50 std::unique_ptr<CachedSurfaceView> CreateView(const ViewKey& view_key); 53 std::unique_ptr<CachedSurfaceView> CreateView(const ViewKey& view_key);
51 54
52 void FlushBufferImpl(); 55 void FlushBufferImpl();
@@ -65,7 +68,6 @@ private:
65 OGLTexture texture; 68 OGLTexture texture;
66 69
67 std::vector<u8> staging_buffer; 70 std::vector<u8> staging_buffer;
68 u8* host_ptr{};
69}; 71};
70 72
71class CachedSurfaceView final { 73class CachedSurfaceView final {
@@ -155,19 +157,21 @@ public:
155 ~TextureCacheOpenGL(); 157 ~TextureCacheOpenGL();
156 158
157protected: 159protected:
158 CachedSurfaceView* TryFastGetSurfaceView(VAddr cpu_addr, u8* host_ptr, 160 CachedSurfaceView* TryFastGetSurfaceView(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
159 const SurfaceParams& new_params, 161 const SurfaceParams& new_params,
160 bool preserve_contents, 162 bool preserve_contents,
161 const std::vector<CachedSurface*>& overlaps); 163 const std::vector<Surface>& overlaps);
162 164
163 std::unique_ptr<CachedSurface> CreateSurface(const SurfaceParams& params); 165 Surface CreateSurface(const SurfaceParams& params);
164 166
165private: 167private:
166 CachedSurfaceView* SurfaceCopy(VAddr cpu_addr, u8* host_ptr, const SurfaceParams& new_params, 168 CachedSurfaceView* SurfaceCopy(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
167 CachedSurface* old_surface, const SurfaceParams& old_params); 169 const SurfaceParams& new_params, const Surface& old_surface,
170 const SurfaceParams& old_params);
168 171
169 CachedSurfaceView* TryCopyAsViews(VAddr cpu_addr, u8* host_ptr, const SurfaceParams& new_params, 172 CachedSurfaceView* TryCopyAsViews(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
170 const std::vector<CachedSurface*>& overlaps); 173 const SurfaceParams& new_params,
174 const std::vector<Surface>& overlaps);
171}; 175};
172 176
173} // namespace OpenGL 177} // namespace OpenGL
diff --git a/src/video_core/texture_cache.cpp b/src/video_core/texture_cache.cpp
index 2994312f4..b47ce6b98 100644
--- a/src/video_core/texture_cache.cpp
+++ b/src/video_core/texture_cache.cpp
@@ -32,12 +32,13 @@ SurfaceParams SurfaceParams::CreateForTexture(Core::System& system,
32 const Tegra::Texture::FullTextureInfo& config) { 32 const Tegra::Texture::FullTextureInfo& config) {
33 SurfaceParams params; 33 SurfaceParams params;
34 params.is_tiled = config.tic.IsTiled(); 34 params.is_tiled = config.tic.IsTiled();
35 params.srgb_conversion = config.tic.IsSrgbConversionEnabled();
35 params.block_width = params.is_tiled ? config.tic.BlockWidth() : 0, 36 params.block_width = params.is_tiled ? config.tic.BlockWidth() : 0,
36 params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0, 37 params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0,
37 params.block_depth = params.is_tiled ? config.tic.BlockDepth() : 0, 38 params.block_depth = params.is_tiled ? config.tic.BlockDepth() : 0,
38 params.tile_width_spacing = params.is_tiled ? (1 << config.tic.tile_width_spacing.Value()) : 1; 39 params.tile_width_spacing = params.is_tiled ? (1 << config.tic.tile_width_spacing.Value()) : 1;
39 params.pixel_format = 40 params.pixel_format = PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value(),
40 PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value(), false); 41 params.srgb_conversion);
41 params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value()); 42 params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value());
42 params.type = GetFormatType(params.pixel_format); 43 params.type = GetFormatType(params.pixel_format);
43 params.target = SurfaceTargetFromTextureType(config.tic.texture_type); 44 params.target = SurfaceTargetFromTextureType(config.tic.texture_type);
@@ -62,6 +63,7 @@ SurfaceParams SurfaceParams::CreateForDepthBuffer(
62 Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout type) { 63 Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout type) {
63 SurfaceParams params; 64 SurfaceParams params;
64 params.is_tiled = type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear; 65 params.is_tiled = type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear;
66 params.srgb_conversion = false;
65 params.block_width = 1 << std::min(block_width, 5U); 67 params.block_width = 1 << std::min(block_width, 5U);
66 params.block_height = 1 << std::min(block_height, 5U); 68 params.block_height = 1 << std::min(block_height, 5U);
67 params.block_depth = 1 << std::min(block_depth, 5U); 69 params.block_depth = 1 << std::min(block_depth, 5U);
@@ -85,6 +87,8 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz
85 SurfaceParams params; 87 SurfaceParams params;
86 params.is_tiled = 88 params.is_tiled =
87 config.memory_layout.type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear; 89 config.memory_layout.type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear;
90 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB ||
91 config.format == Tegra::RenderTargetFormat::RGBA8_SRGB;
88 params.block_width = 1 << config.memory_layout.block_width; 92 params.block_width = 1 << config.memory_layout.block_width;
89 params.block_height = 1 << config.memory_layout.block_height; 93 params.block_height = 1 << config.memory_layout.block_height;
90 params.block_depth = 1 << config.memory_layout.block_depth; 94 params.block_depth = 1 << config.memory_layout.block_depth;
@@ -113,6 +117,8 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
113 const Tegra::Engines::Fermi2D::Regs::Surface& config) { 117 const Tegra::Engines::Fermi2D::Regs::Surface& config) {
114 SurfaceParams params{}; 118 SurfaceParams params{};
115 params.is_tiled = !config.linear; 119 params.is_tiled = !config.linear;
120 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB ||
121 config.format == Tegra::RenderTargetFormat::RGBA8_SRGB;
116 params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 32U) : 0, 122 params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 32U) : 0,
117 params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 32U) : 0, 123 params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 32U) : 0,
118 params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 32U) : 0, 124 params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 32U) : 0,
@@ -162,6 +168,7 @@ u32 SurfaceParams::GetMipBlockHeight(u32 level) const {
162 if (level == 0) { 168 if (level == 0) {
163 return this->block_height; 169 return this->block_height;
164 } 170 }
171
165 const u32 height{GetMipHeight(level)}; 172 const u32 height{GetMipHeight(level)};
166 const u32 default_block_height{GetDefaultBlockHeight()}; 173 const u32 default_block_height{GetDefaultBlockHeight()};
167 const u32 blocks_in_y{(height + default_block_height - 1) / default_block_height}; 174 const u32 blocks_in_y{(height + default_block_height - 1) / default_block_height};
@@ -173,10 +180,12 @@ u32 SurfaceParams::GetMipBlockHeight(u32 level) const {
173} 180}
174 181
175u32 SurfaceParams::GetMipBlockDepth(u32 level) const { 182u32 SurfaceParams::GetMipBlockDepth(u32 level) const {
176 if (level == 0) 183 if (level == 0) {
177 return block_depth; 184 return this->block_depth;
178 if (target != SurfaceTarget::Texture3D) 185 }
186 if (IsLayered()) {
179 return 1; 187 return 1;
188 }
180 189
181 const u32 depth{GetMipDepth(level)}; 190 const u32 depth{GetMipDepth(level)};
182 u32 block_depth = 32; 191 u32 block_depth = 32;
@@ -192,7 +201,7 @@ u32 SurfaceParams::GetMipBlockDepth(u32 level) const {
192std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const { 201std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const {
193 std::size_t offset = 0; 202 std::size_t offset = 0;
194 for (u32 i = 0; i < level; i++) { 203 for (u32 i = 0; i < level; i++) {
195 offset += GetInnerMipmapMemorySize(i, false, IsLayered(), false); 204 offset += GetInnerMipmapMemorySize(i, false, false);
196 } 205 }
197 return offset; 206 return offset;
198} 207}
@@ -200,21 +209,33 @@ std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const {
200std::size_t SurfaceParams::GetHostMipmapLevelOffset(u32 level) const { 209std::size_t SurfaceParams::GetHostMipmapLevelOffset(u32 level) const {
201 std::size_t offset = 0; 210 std::size_t offset = 0;
202 for (u32 i = 0; i < level; i++) { 211 for (u32 i = 0; i < level; i++) {
203 offset += GetInnerMipmapMemorySize(i, true, false, false); 212 offset += GetInnerMipmapMemorySize(i, true, false) * GetNumLayers();
204 } 213 }
205 return offset; 214 return offset;
206} 215}
207 216
208std::size_t SurfaceParams::GetHostMipmapSize(u32 level) const { 217std::size_t SurfaceParams::GetHostMipmapSize(u32 level) const {
209 return GetInnerMipmapMemorySize(level, true, true, false) * GetNumLayers(); 218 return GetInnerMipmapMemorySize(level, true, false) * GetNumLayers();
210} 219}
211 220
212std::size_t SurfaceParams::GetGuestLayerSize() const { 221std::size_t SurfaceParams::GetGuestLayerSize() const {
213 return GetInnerMemorySize(false, true, false); 222 return GetLayerSize(false, false);
223}
224
225std::size_t SurfaceParams::GetLayerSize(bool as_host_size, bool uncompressed) const {
226 std::size_t size = 0;
227 for (u32 level = 0; level < num_levels; ++level) {
228 size += GetInnerMipmapMemorySize(level, as_host_size, uncompressed);
229 }
230 if (is_tiled && IsLayered()) {
231 return Common::AlignUp(size, Tegra::Texture::GetGOBSize() * block_height * block_depth);
232 }
233 return size;
214} 234}
215 235
216std::size_t SurfaceParams::GetHostLayerSize(u32 level) const { 236std::size_t SurfaceParams::GetHostLayerSize(u32 level) const {
217 return GetInnerMipmapMemorySize(level, true, IsLayered(), false); 237 ASSERT(target != SurfaceTarget::Texture3D);
238 return GetInnerMipmapMemorySize(level, true, false);
218} 239}
219 240
220u32 SurfaceParams::GetDefaultBlockWidth() const { 241u32 SurfaceParams::GetDefaultBlockWidth() const {
@@ -273,15 +294,6 @@ bool SurfaceParams::IsPixelFormatZeta() const {
273} 294}
274 295
275void SurfaceParams::CalculateCachedValues() { 296void SurfaceParams::CalculateCachedValues() {
276 guest_size_in_bytes = GetInnerMemorySize(false, false, false);
277
278 // ASTC is uncompressed in software, in emulated as RGBA8
279 if (IsPixelFormatASTC(pixel_format)) {
280 host_size_in_bytes = static_cast<std::size_t>(width * height * depth) * 4ULL;
281 } else {
282 host_size_in_bytes = GetInnerMemorySize(true, false, false);
283 }
284
285 switch (target) { 297 switch (target) {
286 case SurfaceTarget::Texture1D: 298 case SurfaceTarget::Texture1D:
287 case SurfaceTarget::Texture2D: 299 case SurfaceTarget::Texture2D:
@@ -297,28 +309,30 @@ void SurfaceParams::CalculateCachedValues() {
297 default: 309 default:
298 UNREACHABLE(); 310 UNREACHABLE();
299 } 311 }
312
313 guest_size_in_bytes = GetInnerMemorySize(false, false, false);
314
315 // ASTC is uncompressed in software, in emulated as RGBA8
316 if (IsPixelFormatASTC(pixel_format)) {
317 host_size_in_bytes = static_cast<std::size_t>(width * height * depth * 4U);
318 } else {
319 host_size_in_bytes = GetInnerMemorySize(true, false, false);
320 }
300} 321}
301 322
302std::size_t SurfaceParams::GetInnerMipmapMemorySize(u32 level, bool as_host_size, bool layer_only, 323std::size_t SurfaceParams::GetInnerMipmapMemorySize(u32 level, bool as_host_size,
303 bool uncompressed) const { 324 bool uncompressed) const {
304 const bool tiled{as_host_size ? false : is_tiled}; 325 const bool tiled{as_host_size ? false : is_tiled};
305 const u32 width{GetMipmapSize(uncompressed, GetMipWidth(level), GetDefaultBlockWidth())}; 326 const u32 width{GetMipmapSize(uncompressed, GetMipWidth(level), GetDefaultBlockWidth())};
306 const u32 height{GetMipmapSize(uncompressed, GetMipHeight(level), GetDefaultBlockHeight())}; 327 const u32 height{GetMipmapSize(uncompressed, GetMipHeight(level), GetDefaultBlockHeight())};
307 const u32 depth{layer_only ? 1U : GetMipDepth(level)}; 328 const u32 depth{target == SurfaceTarget::Texture3D ? GetMipDepth(level) : 1U};
308 return Tegra::Texture::CalculateSize(tiled, GetBytesPerPixel(), width, height, depth, 329 return Tegra::Texture::CalculateSize(tiled, GetBytesPerPixel(), width, height, depth,
309 GetMipBlockHeight(level), GetMipBlockDepth(level)); 330 GetMipBlockHeight(level), GetMipBlockDepth(level));
310} 331}
311 332
312std::size_t SurfaceParams::GetInnerMemorySize(bool as_host_size, bool layer_only, 333std::size_t SurfaceParams::GetInnerMemorySize(bool as_host_size, bool layer_only,
313 bool uncompressed) const { 334 bool uncompressed) const {
314 std::size_t size = 0; 335 return GetLayerSize(as_host_size, uncompressed) * (layer_only ? 1U : num_layers);
315 for (u32 level = 0; level < num_levels; ++level) {
316 size += GetInnerMipmapMemorySize(level, as_host_size, layer_only, uncompressed);
317 }
318 if (is_tiled && !as_host_size) {
319 size = Common::AlignUp(size, Tegra::Texture::GetGOBSize() * block_height * block_depth);
320 }
321 return size;
322} 336}
323 337
324std::map<u64, std::pair<u32, u32>> SurfaceParams::CreateViewOffsetMap() const { 338std::map<u64, std::pair<u32, u32>> SurfaceParams::CreateViewOffsetMap() const {
diff --git a/src/video_core/texture_cache.h b/src/video_core/texture_cache.h
index 9fd5f074e..0e289d378 100644
--- a/src/video_core/texture_cache.h
+++ b/src/video_core/texture_cache.h
@@ -53,6 +53,7 @@ protected:
53 HasheableSurfaceParams() = default; 53 HasheableSurfaceParams() = default;
54 54
55 bool is_tiled; 55 bool is_tiled;
56 bool srgb_conversion;
56 u32 block_width; 57 u32 block_width;
57 u32 block_height; 58 u32 block_height;
58 u32 block_depth; 59 u32 block_depth;
@@ -92,6 +93,10 @@ public:
92 return is_tiled; 93 return is_tiled;
93 } 94 }
94 95
96 bool GetSrgbConversion() const {
97 return srgb_conversion;
98 }
99
95 u32 GetBlockWidth() const { 100 u32 GetBlockWidth() const {
96 return block_width; 101 return block_width;
97 } 102 }
@@ -211,13 +216,15 @@ private:
211 /// Calculates values that can be deduced from HasheableSurfaceParams. 216 /// Calculates values that can be deduced from HasheableSurfaceParams.
212 void CalculateCachedValues(); 217 void CalculateCachedValues();
213 218
214 /// Returns the size of a given mipmap level. 219 /// Returns the size of a given mipmap level inside a layer.
215 std::size_t GetInnerMipmapMemorySize(u32 level, bool as_host_size, bool layer_only, 220 std::size_t GetInnerMipmapMemorySize(u32 level, bool as_host_size, bool uncompressed) const;
216 bool uncompressed) const;
217 221
218 /// Returns the size of all mipmap levels and aligns as needed. 222 /// Returns the size of all mipmap levels and aligns as needed.
219 std::size_t GetInnerMemorySize(bool as_host_size, bool layer_only, bool uncompressed) const; 223 std::size_t GetInnerMemorySize(bool as_host_size, bool layer_only, bool uncompressed) const;
220 224
225 /// Returns the size of a layer
226 std::size_t GetLayerSize(bool as_host_size, bool uncompressed) const;
227
221 /// Returns true if the passed view width and height match the size of this params in a given 228 /// Returns true if the passed view width and height match the size of this params in a given
222 /// mipmap level. 229 /// mipmap level.
223 bool IsDimensionValid(const SurfaceParams& view_params, u32 level) const; 230 bool IsDimensionValid(const SurfaceParams& view_params, u32 level) const;
@@ -277,13 +284,13 @@ public:
277 284
278 virtual TExecutionContext UploadTexture(TExecutionContext exctx) = 0; 285 virtual TExecutionContext UploadTexture(TExecutionContext exctx) = 0;
279 286
280 TView* TryGetView(VAddr view_addr, const SurfaceParams& view_params) { 287 TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) {
281 if (view_addr < cpu_addr || !params.IsFamiliar(view_params)) { 288 if (view_addr < gpu_addr || !params.IsFamiliar(view_params)) {
282 // It can't be a view if it's in a prior address. 289 // It can't be a view if it's in a prior address.
283 return {}; 290 return {};
284 } 291 }
285 292
286 const auto relative_offset{static_cast<u64>(view_addr - cpu_addr)}; 293 const auto relative_offset{static_cast<u64>(view_addr - gpu_addr)};
287 const auto it{view_offset_map.find(relative_offset)}; 294 const auto it{view_offset_map.find(relative_offset)};
288 if (it == view_offset_map.end()) { 295 if (it == view_offset_map.end()) {
289 // Couldn't find an aligned view. 296 // Couldn't find an aligned view.
@@ -298,6 +305,11 @@ public:
298 return GetView(layer, view_params.GetNumLayers(), level, view_params.GetNumLevels()); 305 return GetView(layer, view_params.GetNumLayers(), level, view_params.GetNumLevels());
299 } 306 }
300 307
308 GPUVAddr GetGpuAddr() const {
309 ASSERT(is_registered);
310 return gpu_addr;
311 }
312
301 VAddr GetCpuAddr() const { 313 VAddr GetCpuAddr() const {
302 ASSERT(is_registered); 314 ASSERT(is_registered);
303 return cpu_addr; 315 return cpu_addr;
@@ -325,22 +337,20 @@ public:
325 return params; 337 return params;
326 } 338 }
327 339
328 TView* GetView(VAddr view_addr, const SurfaceParams& view_params) { 340 TView* GetView(GPUVAddr view_addr, const SurfaceParams& view_params) {
329 TView* view{TryGetView(view_addr, view_params)}; 341 TView* view{TryGetView(view_addr, view_params)};
330 ASSERT(view != nullptr); 342 ASSERT(view != nullptr);
331 return view; 343 return view;
332 } 344 }
333 345
334 void Register(VAddr cpu_addr_, u8* host_ptr_) { 346 void Register(GPUVAddr gpu_addr_, VAddr cpu_addr_, u8* host_ptr_) {
335 ASSERT(!is_registered); 347 ASSERT(!is_registered);
336 is_registered = true; 348 is_registered = true;
349 gpu_addr = gpu_addr_;
337 cpu_addr = cpu_addr_; 350 cpu_addr = cpu_addr_;
338 host_ptr = host_ptr_; 351 host_ptr = host_ptr_;
339 cache_addr = ToCacheAddr(host_ptr_); 352 cache_addr = ToCacheAddr(host_ptr_);
340 } 353 DecorateSurfaceName();
341
342 void Register(VAddr cpu_addr_) {
343 Register(cpu_addr_, Memory::GetPointer(cpu_addr_));
344 } 354 }
345 355
346 void Unregister() { 356 void Unregister() {
@@ -358,6 +368,8 @@ protected:
358 368
359 ~SurfaceBase() = default; 369 ~SurfaceBase() = default;
360 370
371 virtual void DecorateSurfaceName() = 0;
372
361 virtual std::unique_ptr<TView> CreateView(const ViewKey& view_key) = 0; 373 virtual std::unique_ptr<TView> CreateView(const ViewKey& view_key) = 0;
362 374
363 bool IsModified() const { 375 bool IsModified() const {
@@ -379,6 +391,7 @@ private:
379 391
380 const std::map<u64, std::pair<u32, u32>> view_offset_map; 392 const std::map<u64, std::pair<u32, u32>> view_offset_map;
381 393
394 GPUVAddr gpu_addr{};
382 VAddr cpu_addr{}; 395 VAddr cpu_addr{};
383 u8* host_ptr{}; 396 u8* host_ptr{};
384 CacheAddr cache_addr{}; 397 CacheAddr cache_addr{};
@@ -392,12 +405,12 @@ class TextureCache {
392 static_assert(std::is_trivially_copyable_v<TExecutionContext>); 405 static_assert(std::is_trivially_copyable_v<TExecutionContext>);
393 406
394 using ResultType = std::tuple<TView*, TExecutionContext>; 407 using ResultType = std::tuple<TView*, TExecutionContext>;
395 using IntervalMap = boost::icl::interval_map<CacheAddr, std::set<TSurface*>>; 408 using IntervalMap = boost::icl::interval_map<CacheAddr, std::set<std::shared_ptr<TSurface>>>;
396 using IntervalType = typename IntervalMap::interval_type; 409 using IntervalType = typename IntervalMap::interval_type;
397 410
398public: 411public:
399 void InvalidateRegion(CacheAddr addr, std::size_t size) { 412 void InvalidateRegion(CacheAddr addr, std::size_t size) {
400 for (TSurface* surface : GetSurfacesInRegion(addr, size)) { 413 for (const auto& surface : GetSurfacesInRegion(addr, size)) {
401 if (!surface->IsRegistered()) { 414 if (!surface->IsRegistered()) {
402 // Skip duplicates 415 // Skip duplicates
403 continue; 416 continue;
@@ -408,32 +421,25 @@ public:
408 421
409 ResultType GetTextureSurface(TExecutionContext exctx, 422 ResultType GetTextureSurface(TExecutionContext exctx,
410 const Tegra::Texture::FullTextureInfo& config) { 423 const Tegra::Texture::FullTextureInfo& config) {
411 auto& memory_manager{system.GPU().MemoryManager()}; 424 const auto gpu_addr{config.tic.Address()};
412 const auto cpu_addr{memory_manager.GpuToCpuAddress(config.tic.Address())}; 425 if (!gpu_addr) {
413 if (!cpu_addr) {
414 return {{}, exctx}; 426 return {{}, exctx};
415 } 427 }
416 const auto params{SurfaceParams::CreateForTexture(system, config)}; 428 const auto params{SurfaceParams::CreateForTexture(system, config)};
417 return GetSurfaceView(exctx, *cpu_addr, params, true); 429 return GetSurfaceView(exctx, gpu_addr, params, true);
418 } 430 }
419 431
420 ResultType GetDepthBufferSurface(TExecutionContext exctx, bool preserve_contents) { 432 ResultType GetDepthBufferSurface(TExecutionContext exctx, bool preserve_contents) {
421 const auto& regs{system.GPU().Maxwell3D().regs}; 433 const auto& regs{system.GPU().Maxwell3D().regs};
422 if (!regs.zeta.Address() || !regs.zeta_enable) { 434 const auto gpu_addr{regs.zeta.Address()};
435 if (!gpu_addr || !regs.zeta_enable) {
423 return {{}, exctx}; 436 return {{}, exctx};
424 } 437 }
425
426 auto& memory_manager{system.GPU().MemoryManager()};
427 const auto cpu_addr{memory_manager.GpuToCpuAddress(regs.zeta.Address())};
428 if (!cpu_addr) {
429 return {{}, exctx};
430 }
431
432 const auto depth_params{SurfaceParams::CreateForDepthBuffer( 438 const auto depth_params{SurfaceParams::CreateForDepthBuffer(
433 system, regs.zeta_width, regs.zeta_height, regs.zeta.format, 439 system, regs.zeta_width, regs.zeta_height, regs.zeta.format,
434 regs.zeta.memory_layout.block_width, regs.zeta.memory_layout.block_height, 440 regs.zeta.memory_layout.block_width, regs.zeta.memory_layout.block_height,
435 regs.zeta.memory_layout.block_depth, regs.zeta.memory_layout.type)}; 441 regs.zeta.memory_layout.block_depth, regs.zeta.memory_layout.type)};
436 return GetSurfaceView(exctx, *cpu_addr, depth_params, preserve_contents); 442 return GetSurfaceView(exctx, gpu_addr, depth_params, preserve_contents);
437 } 443 }
438 444
439 ResultType GetColorBufferSurface(TExecutionContext exctx, std::size_t index, 445 ResultType GetColorBufferSurface(TExecutionContext exctx, std::size_t index,
@@ -448,25 +454,23 @@ public:
448 454
449 auto& memory_manager{system.GPU().MemoryManager()}; 455 auto& memory_manager{system.GPU().MemoryManager()};
450 const auto& config{system.GPU().Maxwell3D().regs.rt[index]}; 456 const auto& config{system.GPU().Maxwell3D().regs.rt[index]};
451 const auto cpu_addr{memory_manager.GpuToCpuAddress( 457 const auto gpu_addr{config.Address() +
452 config.Address() + config.base_layer * config.layer_stride * sizeof(u32))}; 458 config.base_layer * config.layer_stride * sizeof(u32)};
453 if (!cpu_addr) { 459 if (!gpu_addr) {
454 return {{}, exctx}; 460 return {{}, exctx};
455 } 461 }
456 462
457 return GetSurfaceView(exctx, *cpu_addr, SurfaceParams::CreateForFramebuffer(system, index), 463 return GetSurfaceView(exctx, gpu_addr, SurfaceParams::CreateForFramebuffer(system, index),
458 preserve_contents); 464 preserve_contents);
459 } 465 }
460 466
461 ResultType GetFermiSurface(TExecutionContext exctx, 467 ResultType GetFermiSurface(TExecutionContext exctx,
462 const Tegra::Engines::Fermi2D::Regs::Surface& config) { 468 const Tegra::Engines::Fermi2D::Regs::Surface& config) {
463 const auto cpu_addr{system.GPU().MemoryManager().GpuToCpuAddress(config.Address())}; 469 return GetSurfaceView(exctx, config.Address(),
464 ASSERT(cpu_addr); 470 SurfaceParams::CreateForFermiCopySurface(config), true);
465 return GetSurfaceView(exctx, *cpu_addr, SurfaceParams::CreateForFermiCopySurface(config),
466 true);
467 } 471 }
468 472
469 TSurface* TryFindFramebufferSurface(const u8* host_ptr) const { 473 std::shared_ptr<TSurface> TryFindFramebufferSurface(const u8* host_ptr) const {
470 const auto it{registered_surfaces.find(ToCacheAddr(host_ptr))}; 474 const auto it{registered_surfaces.find(ToCacheAddr(host_ptr))};
471 return it != registered_surfaces.end() ? *it->second.begin() : nullptr; 475 return it != registered_surfaces.end() ? *it->second.begin() : nullptr;
472 } 476 }
@@ -477,56 +481,68 @@ protected:
477 481
478 ~TextureCache() = default; 482 ~TextureCache() = default;
479 483
480 virtual ResultType TryFastGetSurfaceView(TExecutionContext exctx, VAddr cpu_addr, u8* host_ptr, 484 virtual ResultType TryFastGetSurfaceView(
481 const SurfaceParams& params, bool preserve_contents, 485 TExecutionContext exctx, GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
482 const std::vector<TSurface*>& overlaps) = 0; 486 const SurfaceParams& params, bool preserve_contents,
487 const std::vector<std::shared_ptr<TSurface>>& overlaps) = 0;
483 488
484 virtual std::unique_ptr<TSurface> CreateSurface(const SurfaceParams& params) = 0; 489 virtual std::shared_ptr<TSurface> CreateSurface(const SurfaceParams& params) = 0;
485 490
486 void Register(TSurface* surface, VAddr cpu_addr, u8* host_ptr) { 491 void Register(std::shared_ptr<TSurface> surface, GPUVAddr gpu_addr, VAddr cpu_addr,
487 surface->Register(cpu_addr, host_ptr); 492 u8* host_ptr) {
493 surface->Register(gpu_addr, cpu_addr, host_ptr);
488 registered_surfaces.add({GetSurfaceInterval(surface), {surface}}); 494 registered_surfaces.add({GetSurfaceInterval(surface), {surface}});
489 rasterizer.UpdatePagesCachedCount(surface->GetCpuAddr(), surface->GetSizeInBytes(), 1); 495 rasterizer.UpdatePagesCachedCount(surface->GetCpuAddr(), surface->GetSizeInBytes(), 1);
490 } 496 }
491 497
492 void Unregister(TSurface* surface) { 498 void Unregister(std::shared_ptr<TSurface> surface) {
493 registered_surfaces.subtract({GetSurfaceInterval(surface), {surface}}); 499 registered_surfaces.subtract({GetSurfaceInterval(surface), {surface}});
494 rasterizer.UpdatePagesCachedCount(surface->GetCpuAddr(), surface->GetSizeInBytes(), -1); 500 rasterizer.UpdatePagesCachedCount(surface->GetCpuAddr(), surface->GetSizeInBytes(), -1);
495 surface->Unregister(); 501 surface->Unregister();
496 } 502 }
497 503
498 TSurface* GetUncachedSurface(const SurfaceParams& params) { 504 std::shared_ptr<TSurface> GetUncachedSurface(const SurfaceParams& params) {
499 if (TSurface* surface = TryGetReservedSurface(params); surface) 505 if (const auto surface = TryGetReservedSurface(params); surface)
500 return surface; 506 return surface;
501 // No reserved surface available, create a new one and reserve it 507 // No reserved surface available, create a new one and reserve it
502 auto new_surface{CreateSurface(params)}; 508 auto new_surface{CreateSurface(params)};
503 TSurface* surface{new_surface.get()}; 509 ReserveSurface(params, new_surface);
504 ReserveSurface(params, std::move(new_surface)); 510 return new_surface;
505 return surface;
506 } 511 }
507 512
508 Core::System& system; 513 Core::System& system;
509 514
510private: 515private:
511 ResultType GetSurfaceView(TExecutionContext exctx, VAddr cpu_addr, const SurfaceParams& params, 516 ResultType GetSurfaceView(TExecutionContext exctx, GPUVAddr gpu_addr,
512 bool preserve_contents) { 517 const SurfaceParams& params, bool preserve_contents) {
513 const auto host_ptr{Memory::GetPointer(cpu_addr)}; 518 auto& memory_manager{system.GPU().MemoryManager()};
519 const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr)};
520 DEBUG_ASSERT(cpu_addr);
521
522 const auto host_ptr{memory_manager.GetPointer(gpu_addr)};
514 const auto cache_addr{ToCacheAddr(host_ptr)}; 523 const auto cache_addr{ToCacheAddr(host_ptr)};
515 const auto overlaps{GetSurfacesInRegion(cache_addr, params.GetGuestSizeInBytes())}; 524 const auto overlaps{GetSurfacesInRegion(cache_addr, params.GetGuestSizeInBytes())};
516 if (overlaps.empty()) { 525 if (overlaps.empty()) {
517 return LoadSurfaceView(exctx, cpu_addr, host_ptr, params, preserve_contents); 526 return LoadSurfaceView(exctx, gpu_addr, *cpu_addr, host_ptr, params, preserve_contents);
518 } 527 }
519 528
520 if (overlaps.size() == 1) { 529 if (overlaps.size() == 1) {
521 if (TView* view = overlaps[0]->TryGetView(cpu_addr, params); view) 530 if (TView* view = overlaps[0]->TryGetView(gpu_addr, params); view) {
522 return {view, exctx}; 531 return {view, exctx};
532 }
523 } 533 }
524 534
525 TView* fast_view; 535 TView* fast_view;
526 std::tie(fast_view, exctx) = 536 std::tie(fast_view, exctx) = TryFastGetSurfaceView(exctx, gpu_addr, *cpu_addr, host_ptr,
527 TryFastGetSurfaceView(exctx, cpu_addr, host_ptr, params, preserve_contents, overlaps); 537 params, preserve_contents, overlaps);
538
539 if (!fast_view) {
540 std::sort(overlaps.begin(), overlaps.end(), [](const auto& lhs, const auto& rhs) {
541 return lhs->GetModificationTick() < rhs->GetModificationTick();
542 });
543 }
528 544
529 for (TSurface* surface : overlaps) { 545 for (const auto& surface : overlaps) {
530 if (!fast_view) { 546 if (!fast_view) {
531 // Flush even when we don't care about the contents, to preserve memory not written 547 // Flush even when we don't care about the contents, to preserve memory not written
532 // by the new surface. 548 // by the new surface.
@@ -539,57 +555,59 @@ private:
539 return {fast_view, exctx}; 555 return {fast_view, exctx};
540 } 556 }
541 557
542 return LoadSurfaceView(exctx, cpu_addr, host_ptr, params, preserve_contents); 558 return LoadSurfaceView(exctx, gpu_addr, *cpu_addr, host_ptr, params, preserve_contents);
543 } 559 }
544 560
545 ResultType LoadSurfaceView(TExecutionContext exctx, VAddr cpu_addr, u8* host_ptr, 561 ResultType LoadSurfaceView(TExecutionContext exctx, GPUVAddr gpu_addr, VAddr cpu_addr,
546 const SurfaceParams& params, bool preserve_contents) { 562 u8* host_ptr, const SurfaceParams& params, bool preserve_contents) {
547 TSurface* new_surface{GetUncachedSurface(params)}; 563 const auto new_surface{GetUncachedSurface(params)};
548 Register(new_surface, cpu_addr, host_ptr); 564 Register(new_surface, gpu_addr, cpu_addr, host_ptr);
549 if (preserve_contents) { 565 if (preserve_contents) {
550 exctx = LoadSurface(exctx, new_surface); 566 exctx = LoadSurface(exctx, new_surface);
551 } 567 }
552 return {new_surface->GetView(cpu_addr, params), exctx}; 568 return {new_surface->GetView(gpu_addr, params), exctx};
553 } 569 }
554 570
555 TExecutionContext LoadSurface(TExecutionContext exctx, TSurface* surface) { 571 TExecutionContext LoadSurface(TExecutionContext exctx,
572 const std::shared_ptr<TSurface>& surface) {
556 surface->LoadBuffer(); 573 surface->LoadBuffer();
557 exctx = surface->UploadTexture(exctx); 574 exctx = surface->UploadTexture(exctx);
558 surface->MarkAsModified(false); 575 surface->MarkAsModified(false);
559 return exctx; 576 return exctx;
560 } 577 }
561 578
562 std::vector<TSurface*> GetSurfacesInRegion(CacheAddr cache_addr, std::size_t size) const { 579 std::vector<std::shared_ptr<TSurface>> GetSurfacesInRegion(CacheAddr cache_addr,
580 std::size_t size) const {
563 if (size == 0) { 581 if (size == 0) {
564 return {}; 582 return {};
565 } 583 }
566 const IntervalType interval{cache_addr, cache_addr + size}; 584 const IntervalType interval{cache_addr, cache_addr + size};
567 585
568 std::vector<TSurface*> surfaces; 586 std::vector<std::shared_ptr<TSurface>> surfaces;
569 for (auto& pair : boost::make_iterator_range(registered_surfaces.equal_range(interval))) { 587 for (auto& pair : boost::make_iterator_range(registered_surfaces.equal_range(interval))) {
570 surfaces.push_back(*pair.second.begin()); 588 surfaces.push_back(*pair.second.begin());
571 } 589 }
572 return surfaces; 590 return surfaces;
573 } 591 }
574 592
575 void ReserveSurface(const SurfaceParams& params, std::unique_ptr<TSurface> surface) { 593 void ReserveSurface(const SurfaceParams& params, std::shared_ptr<TSurface> surface) {
576 surface_reserve[params].push_back(std::move(surface)); 594 surface_reserve[params].push_back(std::move(surface));
577 } 595 }
578 596
579 TSurface* TryGetReservedSurface(const SurfaceParams& params) { 597 std::shared_ptr<TSurface> TryGetReservedSurface(const SurfaceParams& params) {
580 auto search{surface_reserve.find(params)}; 598 auto search{surface_reserve.find(params)};
581 if (search == surface_reserve.end()) { 599 if (search == surface_reserve.end()) {
582 return {}; 600 return {};
583 } 601 }
584 for (auto& surface : search->second) { 602 for (auto& surface : search->second) {
585 if (!surface->IsRegistered()) { 603 if (!surface->IsRegistered()) {
586 return surface.get(); 604 return surface;
587 } 605 }
588 } 606 }
589 return {}; 607 return {};
590 } 608 }
591 609
592 IntervalType GetSurfaceInterval(TSurface* surface) const { 610 IntervalType GetSurfaceInterval(std::shared_ptr<TSurface> surface) const {
593 return IntervalType::right_open(surface->GetCacheAddr(), 611 return IntervalType::right_open(surface->GetCacheAddr(),
594 surface->GetCacheAddr() + surface->GetSizeInBytes()); 612 surface->GetCacheAddr() + surface->GetSizeInBytes());
595 } 613 }
@@ -601,7 +619,7 @@ private:
601 /// The surface reserve is a "backup" cache, this is where we put unique surfaces that have 619 /// The surface reserve is a "backup" cache, this is where we put unique surfaces that have
602 /// previously been used. This is to prevent surfaces from being constantly created and 620 /// previously been used. This is to prevent surfaces from being constantly created and
603 /// destroyed when used with different surface parameters. 621 /// destroyed when used with different surface parameters.
604 std::unordered_map<SurfaceParams, std::list<std::unique_ptr<TSurface>>> surface_reserve; 622 std::unordered_map<SurfaceParams, std::list<std::shared_ptr<TSurface>>> surface_reserve;
605}; 623};
606 624
607struct DummyExecutionContext {}; 625struct DummyExecutionContext {};
@@ -631,7 +649,7 @@ public:
631 return RemoveContext(Base::GetFermiSurface({}, config)); 649 return RemoveContext(Base::GetFermiSurface({}, config));
632 } 650 }
633 651
634 TSurface* TryFindFramebufferSurface(const u8* host_ptr) const { 652 std::shared_ptr<TSurface> TryFindFramebufferSurface(const u8* host_ptr) const {
635 return Base::TryFindFramebufferSurface(host_ptr); 653 return Base::TryFindFramebufferSurface(host_ptr);
636 } 654 }
637 655
@@ -640,15 +658,18 @@ protected:
640 VideoCore::RasterizerInterface& rasterizer) 658 VideoCore::RasterizerInterface& rasterizer)
641 : TextureCache<TSurface, TView, DummyExecutionContext>{system, rasterizer} {} 659 : TextureCache<TSurface, TView, DummyExecutionContext>{system, rasterizer} {}
642 660
643 virtual TView* TryFastGetSurfaceView(VAddr cpu_addr, u8* host_ptr, const SurfaceParams& params, 661 virtual TView* TryFastGetSurfaceView(
644 bool preserve_contents, 662 GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr, const SurfaceParams& params,
645 const std::vector<TSurface*>& overlaps) = 0; 663 bool preserve_contents, const std::vector<std::shared_ptr<TSurface>>& overlaps) = 0;
646 664
647private: 665private:
648 std::tuple<TView*, DummyExecutionContext> TryFastGetSurfaceView( 666 std::tuple<TView*, DummyExecutionContext> TryFastGetSurfaceView(
649 DummyExecutionContext, VAddr cpu_addr, u8* host_ptr, const SurfaceParams& params, 667 DummyExecutionContext, GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
650 bool preserve_contents, const std::vector<TSurface*>& overlaps) { 668 const SurfaceParams& params, bool preserve_contents,
651 return {TryFastGetSurfaceView(cpu_addr, host_ptr, params, preserve_contents, overlaps), {}}; 669 const std::vector<std::shared_ptr<TSurface>>& overlaps) {
670 return {TryFastGetSurfaceView(gpu_addr, cpu_addr, host_ptr, params, preserve_contents,
671 overlaps),
672 {}};
652 } 673 }
653 674
654 TView* RemoveContext(std::tuple<TView*, DummyExecutionContext> return_value) { 675 TView* RemoveContext(std::tuple<TView*, DummyExecutionContext> return_value) {