diff options
| author | 2019-05-10 17:59:18 -0400 | |
|---|---|---|
| committer | 2019-06-20 21:36:12 -0300 | |
| commit | a4a58be2d46e95df4cead2916b6efbd658a0deaa (patch) | |
| tree | fe1d66d69101467c47167af9c66f17a95d961ed7 /src | |
| parent | video_core: Use un-shifted block sizes to avoid integer divisions (diff) | |
| download | yuzu-a4a58be2d46e95df4cead2916b6efbd658a0deaa.tar.gz yuzu-a4a58be2d46e95df4cead2916b6efbd658a0deaa.tar.xz yuzu-a4a58be2d46e95df4cead2916b6efbd658a0deaa.zip | |
texture_cache: Implement L1_Inner_cache
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index f35d0c88f..ad0fbd7ce 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -395,6 +395,26 @@ private: | |||
| 395 | 395 | ||
| 396 | const auto host_ptr{memory_manager->GetPointer(gpu_addr)}; | 396 | const auto host_ptr{memory_manager->GetPointer(gpu_addr)}; |
| 397 | const auto cache_addr{ToCacheAddr(host_ptr)}; | 397 | const auto cache_addr{ToCacheAddr(host_ptr)}; |
| 398 | |||
| 399 | if (l1_cache.count(cache_addr) > 0) { | ||
| 400 | TSurface current_surface = l1_cache[cache_addr]; | ||
| 401 | if (!current_surface->MatchesTopology(params)) { | ||
| 402 | std::vector<TSurface> overlaps{current_surface}; | ||
| 403 | return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, true); | ||
| 404 | } | ||
| 405 | MatchStructureResult s_result = current_surface->MatchesStructure(params); | ||
| 406 | if (s_result != MatchStructureResult::None && | ||
| 407 | current_surface->GetGpuAddr() == gpu_addr && | ||
| 408 | (params.target != SurfaceTarget::Texture3D || | ||
| 409 | current_surface->MatchTarget(params.target))) { | ||
| 410 | if (s_result == MatchStructureResult::FullMatch) { | ||
| 411 | return ManageStructuralMatch(current_surface, params); | ||
| 412 | } else { | ||
| 413 | return RebuildSurface(current_surface, params); | ||
| 414 | } | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 398 | const std::size_t candidate_size = params.GetGuestSizeInBytes(); | 418 | const std::size_t candidate_size = params.GetGuestSizeInBytes(); |
| 399 | auto overlaps{GetSurfacesInRegion(cache_addr, candidate_size)}; | 419 | auto overlaps{GetSurfacesInRegion(cache_addr, candidate_size)}; |
| 400 | 420 | ||
| @@ -410,17 +430,6 @@ private: | |||
| 410 | 430 | ||
| 411 | if (overlaps.size() == 1) { | 431 | if (overlaps.size() == 1) { |
| 412 | TSurface current_surface = overlaps[0]; | 432 | TSurface current_surface = overlaps[0]; |
| 413 | MatchStructureResult s_result = current_surface->MatchesStructure(params); | ||
| 414 | if (s_result != MatchStructureResult::None && | ||
| 415 | current_surface->GetGpuAddr() == gpu_addr && | ||
| 416 | (params.target != SurfaceTarget::Texture3D || | ||
| 417 | current_surface->MatchTarget(params.target))) { | ||
| 418 | if (s_result == MatchStructureResult::FullMatch) { | ||
| 419 | return ManageStructuralMatch(current_surface, params); | ||
| 420 | } else { | ||
| 421 | return RebuildSurface(current_surface, params); | ||
| 422 | } | ||
| 423 | } | ||
| 424 | if (!current_surface->IsInside(gpu_addr, gpu_addr + candidate_size)) { | 433 | if (!current_surface->IsInside(gpu_addr, gpu_addr + candidate_size)) { |
| 425 | return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, false); | 434 | return RecycleSurface(overlaps, params, gpu_addr, preserve_contents, false); |
| 426 | } | 435 | } |
| @@ -473,8 +482,10 @@ private: | |||
| 473 | } | 482 | } |
| 474 | 483 | ||
| 475 | void RegisterInnerCache(TSurface& surface) { | 484 | void RegisterInnerCache(TSurface& surface) { |
| 476 | CacheAddr start = surface->GetCacheAddr() >> registry_page_bits; | 485 | const CacheAddr cache_addr = surface->GetCacheAddr(); |
| 486 | CacheAddr start = cache_addr >> registry_page_bits; | ||
| 477 | const CacheAddr end = (surface->GetCacheAddrEnd() - 1) >> registry_page_bits; | 487 | const CacheAddr end = (surface->GetCacheAddrEnd() - 1) >> registry_page_bits; |
| 488 | l1_cache[cache_addr] = surface; | ||
| 478 | while (start <= end) { | 489 | while (start <= end) { |
| 479 | registry[start].push_back(surface); | 490 | registry[start].push_back(surface); |
| 480 | start++; | 491 | start++; |
| @@ -482,8 +493,10 @@ private: | |||
| 482 | } | 493 | } |
| 483 | 494 | ||
| 484 | void UnregisterInnerCache(TSurface& surface) { | 495 | void UnregisterInnerCache(TSurface& surface) { |
| 485 | CacheAddr start = surface->GetCacheAddr() >> registry_page_bits; | 496 | const CacheAddr cache_addr = surface->GetCacheAddr(); |
| 497 | CacheAddr start = cache_addr >> registry_page_bits; | ||
| 486 | const CacheAddr end = (surface->GetCacheAddrEnd() - 1) >> registry_page_bits; | 498 | const CacheAddr end = (surface->GetCacheAddrEnd() - 1) >> registry_page_bits; |
| 499 | l1_cache.erase(cache_addr); | ||
| 487 | while (start <= end) { | 500 | while (start <= end) { |
| 488 | auto& reg{registry[start]}; | 501 | auto& reg{registry[start]}; |
| 489 | reg.erase(std::find(reg.begin(), reg.end(), surface)); | 502 | reg.erase(std::find(reg.begin(), reg.end(), surface)); |
| @@ -559,6 +572,10 @@ private: | |||
| 559 | static constexpr u64 registry_page_size{1 << registry_page_bits}; | 572 | static constexpr u64 registry_page_size{1 << registry_page_bits}; |
| 560 | std::unordered_map<CacheAddr, std::vector<TSurface>> registry; | 573 | std::unordered_map<CacheAddr, std::vector<TSurface>> registry; |
| 561 | 574 | ||
| 575 | // The L1 Cache is used for fast texture lookup before checking the overlaps | ||
| 576 | // This avoids calculating size and other stuffs. | ||
| 577 | std::unordered_map<CacheAddr, TSurface> l1_cache; | ||
| 578 | |||
| 562 | /// The surface reserve is a "backup" cache, this is where we put unique surfaces that have | 579 | /// The surface reserve is a "backup" cache, this is where we put unique surfaces that have |
| 563 | /// previously been used. This is to prevent surfaces from being constantly created and | 580 | /// previously been used. This is to prevent surfaces from being constantly created and |
| 564 | /// destroyed when used with different surface parameters. | 581 | /// destroyed when used with different surface parameters. |