summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache.h
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-04-24 16:35:54 -0300
committerGravatar ReinUsesLisp2019-06-20 21:36:11 -0300
commit1b4503c571d3b961efe74fa7e35d5fa14941ec09 (patch)
treefb732f50d8bd2855f3fa7657c7c6d36c58134d89 /src/video_core/texture_cache.h
parenttexture_cache: Move staging buffer into a generic implementation (diff)
downloadyuzu-1b4503c571d3b961efe74fa7e35d5fa14941ec09.tar.gz
yuzu-1b4503c571d3b961efe74fa7e35d5fa14941ec09.tar.xz
yuzu-1b4503c571d3b961efe74fa7e35d5fa14941ec09.zip
texture_cache: Split texture cache into different files
Diffstat (limited to 'src/video_core/texture_cache.h')
-rw-r--r--src/video_core/texture_cache.h750
1 files changed, 0 insertions, 750 deletions
diff --git a/src/video_core/texture_cache.h b/src/video_core/texture_cache.h
deleted file mode 100644
index 90c72cb15..000000000
--- a/src/video_core/texture_cache.h
+++ /dev/null
@@ -1,750 +0,0 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <list>
8#include <memory>
9#include <set>
10#include <tuple>
11#include <type_traits>
12#include <unordered_map>
13
14#include <boost/icl/interval_map.hpp>
15#include <boost/range/iterator_range.hpp>
16
17#include "common/assert.h"
18#include "common/common_types.h"
19#include "core/memory.h"
20#include "video_core/engines/fermi_2d.h"
21#include "video_core/engines/maxwell_3d.h"
22#include "video_core/gpu.h"
23#include "video_core/memory_manager.h"
24#include "video_core/rasterizer_interface.h"
25#include "video_core/surface.h"
26
27namespace Core {
28class System;
29}
30
31namespace Tegra::Texture {
32struct FullTextureInfo;
33}
34
35namespace VideoCore {
36class RasterizerInterface;
37}
38
39namespace VideoCommon {
40
41class HasheableSurfaceParams {
42public:
43 std::size_t Hash() const;
44
45 bool operator==(const HasheableSurfaceParams& rhs) const;
46
47 bool operator!=(const HasheableSurfaceParams& rhs) const {
48 return !operator==(rhs);
49 }
50
51protected:
52 // Avoid creation outside of a managed environment.
53 HasheableSurfaceParams() = default;
54
55 bool is_tiled;
56 bool srgb_conversion;
57 u32 block_width;
58 u32 block_height;
59 u32 block_depth;
60 u32 tile_width_spacing;
61 u32 width;
62 u32 height;
63 u32 depth;
64 u32 pitch;
65 u32 unaligned_height;
66 u32 num_levels;
67 VideoCore::Surface::PixelFormat pixel_format;
68 VideoCore::Surface::ComponentType component_type;
69 VideoCore::Surface::SurfaceType type;
70 VideoCore::Surface::SurfaceTarget target;
71};
72
73class SurfaceParams final : public HasheableSurfaceParams {
74public:
75 /// Creates SurfaceCachedParams from a texture configuration.
76 static SurfaceParams CreateForTexture(Core::System& system,
77 const Tegra::Texture::FullTextureInfo& config);
78
79 /// Creates SurfaceCachedParams for a depth buffer configuration.
80 static SurfaceParams CreateForDepthBuffer(
81 Core::System& system, u32 zeta_width, u32 zeta_height, Tegra::DepthFormat format,
82 u32 block_width, u32 block_height, u32 block_depth,
83 Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout type);
84
85 /// Creates SurfaceCachedParams from a framebuffer configuration.
86 static SurfaceParams CreateForFramebuffer(Core::System& system, std::size_t index);
87
88 /// Creates SurfaceCachedParams from a Fermi2D surface configuration.
89 static SurfaceParams CreateForFermiCopySurface(
90 const Tegra::Engines::Fermi2D::Regs::Surface& config);
91
92 bool IsTiled() const {
93 return is_tiled;
94 }
95
96 bool GetSrgbConversion() const {
97 return srgb_conversion;
98 }
99
100 u32 GetBlockWidth() const {
101 return block_width;
102 }
103
104 u32 GetTileWidthSpacing() const {
105 return tile_width_spacing;
106 }
107
108 u32 GetWidth() const {
109 return width;
110 }
111
112 u32 GetHeight() const {
113 return height;
114 }
115
116 u32 GetDepth() const {
117 return depth;
118 }
119
120 u32 GetPitch() const {
121 return pitch;
122 }
123
124 u32 GetNumLevels() const {
125 return num_levels;
126 }
127
128 VideoCore::Surface::PixelFormat GetPixelFormat() const {
129 return pixel_format;
130 }
131
132 VideoCore::Surface::ComponentType GetComponentType() const {
133 return component_type;
134 }
135
136 VideoCore::Surface::SurfaceTarget GetTarget() const {
137 return target;
138 }
139
140 VideoCore::Surface::SurfaceType GetType() const {
141 return type;
142 }
143
144 std::size_t GetGuestSizeInBytes() const {
145 return guest_size_in_bytes;
146 }
147
148 std::size_t GetHostSizeInBytes() const {
149 return host_size_in_bytes;
150 }
151
152 u32 GetNumLayers() const {
153 return num_layers;
154 }
155
156 /// Returns the width of a given mipmap level.
157 u32 GetMipWidth(u32 level) const;
158
159 /// Returns the height of a given mipmap level.
160 u32 GetMipHeight(u32 level) const;
161
162 /// Returns the depth of a given mipmap level.
163 u32 GetMipDepth(u32 level) const;
164
165 /// Returns true if these parameters are from a layered surface.
166 bool IsLayered() const;
167
168 /// Returns the block height of a given mipmap level.
169 u32 GetMipBlockHeight(u32 level) const;
170
171 /// Returns the block depth of a given mipmap level.
172 u32 GetMipBlockDepth(u32 level) const;
173
174 /// Returns the offset in bytes in guest memory of a given mipmap level.
175 std::size_t GetGuestMipmapLevelOffset(u32 level) const;
176
177 /// Returns the offset in bytes in host memory (linear) of a given mipmap level.
178 std::size_t GetHostMipmapLevelOffset(u32 level) const;
179
180 /// Returns the size in bytes in host memory (linear) of a given mipmap level.
181 std::size_t GetHostMipmapSize(u32 level) const;
182
183 /// Returns the size of a layer in bytes in guest memory.
184 std::size_t GetGuestLayerSize() const;
185
186 /// Returns the size of a layer in bytes in host memory for a given mipmap level.
187 std::size_t GetHostLayerSize(u32 level) const;
188
189 /// Returns the default block width.
190 u32 GetDefaultBlockWidth() const;
191
192 /// Returns the default block height.
193 u32 GetDefaultBlockHeight() const;
194
195 /// Returns the bits per pixel.
196 u32 GetBitsPerPixel() const;
197
198 /// Returns the bytes per pixel.
199 u32 GetBytesPerPixel() const;
200
201 /// Returns true if another surface can be familiar with this. This is a loosely defined term
202 /// that reflects the possibility of these two surface parameters potentially being part of a
203 /// bigger superset.
204 bool IsFamiliar(const SurfaceParams& view_params) const;
205
206 /// Returns true if the pixel format is a depth and/or stencil format.
207 bool IsPixelFormatZeta() const;
208
209 /// Creates a map that redirects an address difference to a layer and mipmap level.
210 std::map<u64, std::pair<u32, u32>> CreateViewOffsetMap() const;
211
212 /// Returns true if the passed surface view parameters is equal or a valid subset of this.
213 bool IsViewValid(const SurfaceParams& view_params, u32 layer, u32 level) const;
214
215private:
216 /// Calculates values that can be deduced from HasheableSurfaceParams.
217 void CalculateCachedValues();
218
219 /// Returns the size of a given mipmap level inside a layer.
220 std::size_t GetInnerMipmapMemorySize(u32 level, bool as_host_size, bool uncompressed) const;
221
222 /// Returns the size of all mipmap levels and aligns as needed.
223 std::size_t GetInnerMemorySize(bool as_host_size, bool layer_only, bool uncompressed) const;
224
225 /// Returns the size of a layer
226 std::size_t GetLayerSize(bool as_host_size, bool uncompressed) const;
227
228 /// Returns true if the passed view width and height match the size of this params in a given
229 /// mipmap level.
230 bool IsDimensionValid(const SurfaceParams& view_params, u32 level) const;
231
232 /// Returns true if the passed view depth match the size of this params in a given mipmap level.
233 bool IsDepthValid(const SurfaceParams& view_params, u32 level) const;
234
235 /// Returns true if the passed view layers and mipmap levels are in bounds.
236 bool IsInBounds(const SurfaceParams& view_params, u32 layer, u32 level) const;
237
238 std::size_t guest_size_in_bytes;
239 std::size_t host_size_in_bytes;
240 u32 num_layers;
241};
242
243struct ViewKey {
244 std::size_t Hash() const;
245
246 bool operator==(const ViewKey& rhs) const;
247
248 u32 base_layer{};
249 u32 num_layers{};
250 u32 base_level{};
251 u32 num_levels{};
252};
253
254} // namespace VideoCommon
255
256namespace std {
257
258template <>
259struct hash<VideoCommon::SurfaceParams> {
260 std::size_t operator()(const VideoCommon::SurfaceParams& k) const noexcept {
261 return k.Hash();
262 }
263};
264
265template <>
266struct hash<VideoCommon::ViewKey> {
267 std::size_t operator()(const VideoCommon::ViewKey& k) const noexcept {
268 return k.Hash();
269 }
270};
271
272} // namespace std
273
274namespace VideoCommon {
275
276class SurfaceBaseImpl {
277public:
278 void LoadBuffer();
279
280 void FlushBuffer();
281
282 GPUVAddr GetGpuAddr() const {
283 ASSERT(is_registered);
284 return gpu_addr;
285 }
286
287 VAddr GetCpuAddr() const {
288 ASSERT(is_registered);
289 return cpu_addr;
290 }
291
292 u8* GetHostPtr() const {
293 ASSERT(is_registered);
294 return host_ptr;
295 }
296
297 CacheAddr GetCacheAddr() const {
298 ASSERT(is_registered);
299 return cache_addr;
300 }
301
302 const SurfaceParams& GetSurfaceParams() const {
303 return params;
304 }
305
306 void Register(GPUVAddr gpu_addr_, VAddr cpu_addr_, u8* host_ptr_) {
307 ASSERT(!is_registered);
308 is_registered = true;
309 gpu_addr = gpu_addr_;
310 cpu_addr = cpu_addr_;
311 host_ptr = host_ptr_;
312 cache_addr = ToCacheAddr(host_ptr_);
313 DecorateSurfaceName();
314 }
315
316 void Unregister() {
317 ASSERT(is_registered);
318 is_registered = false;
319 }
320
321 bool IsRegistered() const {
322 return is_registered;
323 }
324
325 std::size_t GetSizeInBytes() const {
326 return params.GetGuestSizeInBytes();
327 }
328
329 u8* GetStagingBufferLevelData(u32 level) {
330 return staging_buffer.data() + params.GetHostMipmapLevelOffset(level);
331 }
332
333protected:
334 explicit SurfaceBaseImpl(const SurfaceParams& params);
335 ~SurfaceBaseImpl(); // non-virtual is intended
336
337 virtual void DecorateSurfaceName() = 0;
338
339 const SurfaceParams params;
340
341private:
342 GPUVAddr gpu_addr{};
343 VAddr cpu_addr{};
344 u8* host_ptr{};
345 CacheAddr cache_addr{};
346 bool is_registered{};
347
348 std::vector<u8> staging_buffer;
349};
350
351template <typename TTextureCache, typename TView, typename TExecutionContext>
352class SurfaceBase : public SurfaceBaseImpl {
353 static_assert(std::is_trivially_copyable_v<TExecutionContext>);
354
355public:
356 virtual TExecutionContext UploadTexture(TExecutionContext exctx) = 0;
357
358 virtual TExecutionContext DownloadTexture(TExecutionContext exctx) = 0;
359
360 TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) {
361 if (view_addr < GetGpuAddr() || !params.IsFamiliar(view_params)) {
362 // It can't be a view if it's in a prior address.
363 return {};
364 }
365
366 const auto relative_offset{static_cast<u64>(view_addr - GetGpuAddr())};
367 const auto it{view_offset_map.find(relative_offset)};
368 if (it == view_offset_map.end()) {
369 // Couldn't find an aligned view.
370 return {};
371 }
372 const auto [layer, level] = it->second;
373
374 if (!params.IsViewValid(view_params, layer, level)) {
375 return {};
376 }
377
378 return GetView(layer, view_params.GetNumLayers(), level, view_params.GetNumLevels());
379 }
380
381 void MarkAsModified(bool is_modified_) {
382 is_modified = is_modified_;
383 if (is_modified_) {
384 modification_tick = texture_cache.Tick();
385 }
386 }
387
388 TView* GetView(GPUVAddr view_addr, const SurfaceParams& view_params) {
389 TView* view{TryGetView(view_addr, view_params)};
390 ASSERT(view != nullptr);
391 return view;
392 }
393
394 bool IsModified() const {
395 return is_modified;
396 }
397
398 u64 GetModificationTick() const {
399 return modification_tick;
400 }
401
402protected:
403 explicit SurfaceBase(TTextureCache& texture_cache, const SurfaceParams& params)
404 : SurfaceBaseImpl{params}, texture_cache{texture_cache},
405 view_offset_map{params.CreateViewOffsetMap()} {}
406
407 ~SurfaceBase() = default;
408
409 virtual std::unique_ptr<TView> CreateView(const ViewKey& view_key) = 0;
410
411private:
412 TView* GetView(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels) {
413 const ViewKey key{base_layer, num_layers, base_level, num_levels};
414 const auto [entry, is_cache_miss] = views.try_emplace(key);
415 auto& view{entry->second};
416 if (is_cache_miss) {
417 view = CreateView(key);
418 }
419 return view.get();
420 }
421
422 TTextureCache& texture_cache;
423 const std::map<u64, std::pair<u32, u32>> view_offset_map;
424
425 bool is_modified{};
426 u64 modification_tick{};
427 std::unordered_map<ViewKey, std::unique_ptr<TView>> views;
428};
429
430template <typename TSurface, typename TView, typename TExecutionContext>
431class TextureCache {
432 static_assert(std::is_trivially_copyable_v<TExecutionContext>);
433
434 using ResultType = std::tuple<TView*, TExecutionContext>;
435 using IntervalMap = boost::icl::interval_map<CacheAddr, std::set<std::shared_ptr<TSurface>>>;
436 using IntervalType = typename IntervalMap::interval_type;
437
438public:
439 void InvalidateRegion(CacheAddr addr, std::size_t size) {
440 for (const auto& surface : GetSurfacesInRegion(addr, size)) {
441 if (!surface->IsRegistered()) {
442 // Skip duplicates
443 continue;
444 }
445 Unregister(surface);
446 }
447 }
448
449 ResultType GetTextureSurface(TExecutionContext exctx,
450 const Tegra::Texture::FullTextureInfo& config) {
451 const auto gpu_addr{config.tic.Address()};
452 if (!gpu_addr) {
453 return {{}, exctx};
454 }
455 const auto params{SurfaceParams::CreateForTexture(system, config)};
456 return GetSurfaceView(exctx, gpu_addr, params, true);
457 }
458
459 ResultType GetDepthBufferSurface(TExecutionContext exctx, bool preserve_contents) {
460 const auto& regs{system.GPU().Maxwell3D().regs};
461 const auto gpu_addr{regs.zeta.Address()};
462 if (!gpu_addr || !regs.zeta_enable) {
463 return {{}, exctx};
464 }
465 const auto depth_params{SurfaceParams::CreateForDepthBuffer(
466 system, regs.zeta_width, regs.zeta_height, regs.zeta.format,
467 regs.zeta.memory_layout.block_width, regs.zeta.memory_layout.block_height,
468 regs.zeta.memory_layout.block_depth, regs.zeta.memory_layout.type)};
469 return GetSurfaceView(exctx, gpu_addr, depth_params, preserve_contents);
470 }
471
472 ResultType GetColorBufferSurface(TExecutionContext exctx, std::size_t index,
473 bool preserve_contents) {
474 ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets);
475
476 const auto& regs{system.GPU().Maxwell3D().regs};
477 if (index >= regs.rt_control.count || regs.rt[index].Address() == 0 ||
478 regs.rt[index].format == Tegra::RenderTargetFormat::NONE) {
479 return {{}, exctx};
480 }
481
482 auto& memory_manager{system.GPU().MemoryManager()};
483 const auto& config{system.GPU().Maxwell3D().regs.rt[index]};
484 const auto gpu_addr{config.Address() +
485 config.base_layer * config.layer_stride * sizeof(u32)};
486 if (!gpu_addr) {
487 return {{}, exctx};
488 }
489
490 return GetSurfaceView(exctx, gpu_addr, SurfaceParams::CreateForFramebuffer(system, index),
491 preserve_contents);
492 }
493
494 ResultType GetFermiSurface(TExecutionContext exctx,
495 const Tegra::Engines::Fermi2D::Regs::Surface& config) {
496 return GetSurfaceView(exctx, config.Address(),
497 SurfaceParams::CreateForFermiCopySurface(config), true);
498 }
499
500 std::shared_ptr<TSurface> TryFindFramebufferSurface(const u8* host_ptr) const {
501 const auto it{registered_surfaces.find(ToCacheAddr(host_ptr))};
502 return it != registered_surfaces.end() ? *it->second.begin() : nullptr;
503 }
504
505 u64 Tick() {
506 return ++ticks;
507 }
508
509protected:
510 TextureCache(Core::System& system, VideoCore::RasterizerInterface& rasterizer)
511 : system{system}, rasterizer{rasterizer} {}
512
513 ~TextureCache() = default;
514
515 virtual ResultType TryFastGetSurfaceView(
516 TExecutionContext exctx, GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
517 const SurfaceParams& params, bool preserve_contents,
518 const std::vector<std::shared_ptr<TSurface>>& overlaps) = 0;
519
520 virtual std::shared_ptr<TSurface> CreateSurface(const SurfaceParams& params) = 0;
521
522 void Register(std::shared_ptr<TSurface> surface, GPUVAddr gpu_addr, VAddr cpu_addr,
523 u8* host_ptr) {
524 surface->Register(gpu_addr, cpu_addr, host_ptr);
525 registered_surfaces.add({GetSurfaceInterval(surface), {surface}});
526 rasterizer.UpdatePagesCachedCount(surface->GetCpuAddr(), surface->GetSizeInBytes(), 1);
527 }
528
529 void Unregister(std::shared_ptr<TSurface> surface) {
530 registered_surfaces.subtract({GetSurfaceInterval(surface), {surface}});
531 rasterizer.UpdatePagesCachedCount(surface->GetCpuAddr(), surface->GetSizeInBytes(), -1);
532 surface->Unregister();
533 }
534
535 std::shared_ptr<TSurface> GetUncachedSurface(const SurfaceParams& params) {
536 if (const auto surface = TryGetReservedSurface(params); surface)
537 return surface;
538 // No reserved surface available, create a new one and reserve it
539 auto new_surface{CreateSurface(params)};
540 ReserveSurface(params, new_surface);
541 return new_surface;
542 }
543
544 Core::System& system;
545
546private:
547 ResultType GetSurfaceView(TExecutionContext exctx, GPUVAddr gpu_addr,
548 const SurfaceParams& params, bool preserve_contents) {
549 auto& memory_manager{system.GPU().MemoryManager()};
550 const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr)};
551 DEBUG_ASSERT(cpu_addr);
552
553 const auto host_ptr{memory_manager.GetPointer(gpu_addr)};
554 const auto cache_addr{ToCacheAddr(host_ptr)};
555 auto overlaps{GetSurfacesInRegion(cache_addr, params.GetGuestSizeInBytes())};
556 if (overlaps.empty()) {
557 return LoadSurfaceView(exctx, gpu_addr, *cpu_addr, host_ptr, params, preserve_contents);
558 }
559
560 if (overlaps.size() == 1) {
561 if (TView* view = overlaps[0]->TryGetView(gpu_addr, params); view) {
562 return {view, exctx};
563 }
564 }
565
566 TView* fast_view;
567 std::tie(fast_view, exctx) = TryFastGetSurfaceView(exctx, gpu_addr, *cpu_addr, host_ptr,
568 params, preserve_contents, overlaps);
569
570 if (!fast_view) {
571 std::sort(overlaps.begin(), overlaps.end(), [](const auto& lhs, const auto& rhs) {
572 return lhs->GetModificationTick() < rhs->GetModificationTick();
573 });
574 }
575
576 for (const auto& surface : overlaps) {
577 if (!fast_view) {
578 // Flush even when we don't care about the contents, to preserve memory not
579 // written by the new surface.
580 exctx = FlushSurface(exctx, surface);
581 }
582 Unregister(surface);
583 }
584
585 if (fast_view) {
586 return {fast_view, exctx};
587 }
588
589 return LoadSurfaceView(exctx, gpu_addr, *cpu_addr, host_ptr, params, preserve_contents);
590 }
591
592 ResultType LoadSurfaceView(TExecutionContext exctx, GPUVAddr gpu_addr, VAddr cpu_addr,
593 u8* host_ptr, const SurfaceParams& params, bool preserve_contents) {
594 const auto new_surface{GetUncachedSurface(params)};
595 Register(new_surface, gpu_addr, cpu_addr, host_ptr);
596 if (preserve_contents) {
597 exctx = LoadSurface(exctx, new_surface);
598 }
599 return {new_surface->GetView(gpu_addr, params), exctx};
600 }
601
602 TExecutionContext LoadSurface(TExecutionContext exctx,
603 const std::shared_ptr<TSurface>& surface) {
604 surface->LoadBuffer();
605 exctx = surface->UploadTexture(exctx);
606 surface->MarkAsModified(false);
607 return exctx;
608 }
609
610 TExecutionContext FlushSurface(TExecutionContext exctx,
611 const std::shared_ptr<TSurface>& surface) {
612 if (!surface->IsModified()) {
613 return exctx;
614 }
615 exctx = surface->DownloadTexture(exctx);
616 surface->FlushBuffer();
617 return exctx;
618 }
619
620 std::vector<std::shared_ptr<TSurface>> GetSurfacesInRegion(CacheAddr cache_addr,
621 std::size_t size) const {
622 if (size == 0) {
623 return {};
624 }
625 const IntervalType interval{cache_addr, cache_addr + size};
626
627 std::vector<std::shared_ptr<TSurface>> surfaces;
628 for (auto& pair : boost::make_iterator_range(registered_surfaces.equal_range(interval))) {
629 surfaces.push_back(*pair.second.begin());
630 }
631 return surfaces;
632 }
633
634 void ReserveSurface(const SurfaceParams& params, std::shared_ptr<TSurface> surface) {
635 surface_reserve[params].push_back(std::move(surface));
636 }
637
638 std::shared_ptr<TSurface> TryGetReservedSurface(const SurfaceParams& params) {
639 auto search{surface_reserve.find(params)};
640 if (search == surface_reserve.end()) {
641 return {};
642 }
643 for (auto& surface : search->second) {
644 if (!surface->IsRegistered()) {
645 return surface;
646 }
647 }
648 return {};
649 }
650
651 IntervalType GetSurfaceInterval(std::shared_ptr<TSurface> surface) const {
652 return IntervalType::right_open(surface->GetCacheAddr(),
653 surface->GetCacheAddr() + surface->GetSizeInBytes());
654 }
655
656 VideoCore::RasterizerInterface& rasterizer;
657
658 u64 ticks{};
659
660 IntervalMap registered_surfaces;
661
662 /// The surface reserve is a "backup" cache, this is where we put unique surfaces that have
663 /// previously been used. This is to prevent surfaces from being constantly created and
664 /// destroyed when used with different surface parameters.
665 std::unordered_map<SurfaceParams, std::list<std::shared_ptr<TSurface>>> surface_reserve;
666};
667
668struct DummyExecutionContext {};
669
670template <typename TSurface, typename TView>
671class TextureCacheContextless : protected TextureCache<TSurface, TView, DummyExecutionContext> {
672 using Base = TextureCache<TSurface, TView, DummyExecutionContext>;
673
674public:
675 void InvalidateRegion(CacheAddr addr, std::size_t size) {
676 Base::InvalidateRegion(addr, size);
677 }
678
679 TView* GetTextureSurface(const Tegra::Texture::FullTextureInfo& config) {
680 return RemoveContext(Base::GetTextureSurface({}, config));
681 }
682
683 TView* GetDepthBufferSurface(bool preserve_contents) {
684 return RemoveContext(Base::GetDepthBufferSurface({}, preserve_contents));
685 }
686
687 TView* GetColorBufferSurface(std::size_t index, bool preserve_contents) {
688 return RemoveContext(Base::GetColorBufferSurface({}, index, preserve_contents));
689 }
690
691 TView* GetFermiSurface(const Tegra::Engines::Fermi2D::Regs::Surface& config) {
692 return RemoveContext(Base::GetFermiSurface({}, config));
693 }
694
695 std::shared_ptr<TSurface> TryFindFramebufferSurface(const u8* host_ptr) const {
696 return Base::TryFindFramebufferSurface(host_ptr);
697 }
698
699 u64 Tick() {
700 return Base::Tick();
701 }
702
703protected:
704 explicit TextureCacheContextless(Core::System& system,
705 VideoCore::RasterizerInterface& rasterizer)
706 : TextureCache<TSurface, TView, DummyExecutionContext>{system, rasterizer} {}
707
708 virtual TView* TryFastGetSurfaceView(
709 GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr, const SurfaceParams& params,
710 bool preserve_contents, const std::vector<std::shared_ptr<TSurface>>& overlaps) = 0;
711
712private:
713 std::tuple<TView*, DummyExecutionContext> TryFastGetSurfaceView(
714 DummyExecutionContext, GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
715 const SurfaceParams& params, bool preserve_contents,
716 const std::vector<std::shared_ptr<TSurface>>& overlaps) {
717 return {TryFastGetSurfaceView(gpu_addr, cpu_addr, host_ptr, params, preserve_contents,
718 overlaps),
719 {}};
720 }
721
722 TView* RemoveContext(std::tuple<TView*, DummyExecutionContext> return_value) {
723 const auto [view, exctx] = return_value;
724 return view;
725 }
726};
727
728template <typename TTextureCache, typename TView>
729class SurfaceBaseContextless : public SurfaceBase<TTextureCache, TView, DummyExecutionContext> {
730public:
731 DummyExecutionContext DownloadTexture(DummyExecutionContext) {
732 DownloadTextureImpl();
733 return {};
734 }
735
736 DummyExecutionContext UploadTexture(DummyExecutionContext) {
737 UploadTextureImpl();
738 return {};
739 }
740
741protected:
742 explicit SurfaceBaseContextless(TTextureCache& texture_cache, const SurfaceParams& params)
743 : SurfaceBase<TTextureCache, TView, DummyExecutionContext>{texture_cache, params} {}
744
745 virtual void DownloadTextureImpl() = 0;
746
747 virtual void UploadTextureImpl() = 0;
748};
749
750} // namespace VideoCommon