summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-05-10 17:59:18 -0400
committerGravatar ReinUsesLisp2019-06-20 21:36:12 -0300
commita4a58be2d46e95df4cead2916b6efbd658a0deaa (patch)
treefe1d66d69101467c47167af9c66f17a95d961ed7 /src
parentvideo_core: Use un-shifted block sizes to avoid integer divisions (diff)
downloadyuzu-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.h43
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.