diff options
| author | 2019-04-16 20:01:07 -0300 | |
|---|---|---|
| committer | 2019-06-20 21:36:11 -0300 | |
| commit | 4b396f375c0d32b60595f224d06b1b63d6df6b0a (patch) | |
| tree | d61b116481b20802deee2472735e83c053901454 /src/video_core/texture_cache.h | |
| parent | gl_texture_cache: Add copy from multiple overlaps into a single surface (diff) | |
| download | yuzu-4b396f375c0d32b60595f224d06b1b63d6df6b0a.tar.gz yuzu-4b396f375c0d32b60595f224d06b1b63d6df6b0a.tar.xz yuzu-4b396f375c0d32b60595f224d06b1b63d6df6b0a.zip | |
gl_texture_cache: Minor changes
Diffstat (limited to 'src/video_core/texture_cache.h')
| -rw-r--r-- | src/video_core/texture_cache.h | 175 |
1 files changed, 98 insertions, 77 deletions
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 | ||
| 398 | public: | 411 | public: |
| 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 | ||
| 510 | private: | 515 | private: |
| 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 | ||
| 607 | struct DummyExecutionContext {}; | 625 | struct 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 | ||
| 647 | private: | 665 | private: |
| 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) { |