summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-04-25 13:41:57 -0300
committerGravatar ReinUsesLisp2019-06-20 21:36:11 -0300
commit6c410104f4f6953ac37095aa5e65804bf115c026 (patch)
treec508c35c4bc1bf436a22888cd6c150dfbe07edc8 /src/video_core/texture_cache
parentgl_texture_cache: Implement fermi copies (diff)
downloadyuzu-6c410104f4f6953ac37095aa5e65804bf115c026.tar.gz
yuzu-6c410104f4f6953ac37095aa5e65804bf115c026.tar.xz
yuzu-6c410104f4f6953ac37095aa5e65804bf115c026.zip
texture_cache: Remove execution context copies from the texture cache
This is done to simplify the OpenGL implementation, it is needed for Vulkan.
Diffstat (limited to 'src/video_core/texture_cache')
-rw-r--r--src/video_core/texture_cache/surface_base.cpp8
-rw-r--r--src/video_core/texture_cache/surface_base.h8
-rw-r--r--src/video_core/texture_cache/texture_cache.h83
-rw-r--r--src/video_core/texture_cache/texture_cache_contextless.h93
4 files changed, 41 insertions, 151 deletions
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp
index 8680485b4..d0779b502 100644
--- a/src/video_core/texture_cache/surface_base.cpp
+++ b/src/video_core/texture_cache/surface_base.cpp
@@ -53,8 +53,8 @@ void SurfaceBaseImpl::LoadBuffer() {
53 ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {} on texture target {}", 53 ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {} on texture target {}",
54 params.GetBlockWidth(), static_cast<u32>(params.GetTarget())); 54 params.GetBlockWidth(), static_cast<u32>(params.GetTarget()));
55 for (u32 level = 0; level < params.GetNumLevels(); ++level) { 55 for (u32 level = 0; level < params.GetNumLevels(); ++level) {
56 u8* const buffer{GetStagingBufferLevelData(level)}; 56 SwizzleFunc(MortonSwizzleMode::MortonToLinear, host_ptr, params,
57 SwizzleFunc(MortonSwizzleMode::MortonToLinear, host_ptr, params, buffer, level); 57 GetStagingBufferLevelData(level), level);
58 } 58 }
59 } else { 59 } else {
60 ASSERT_MSG(params.GetNumLevels() == 1, "Linear mipmap loading is not implemented"); 60 ASSERT_MSG(params.GetNumLevels() == 1, "Linear mipmap loading is not implemented");
@@ -89,8 +89,8 @@ void SurfaceBaseImpl::FlushBuffer() {
89 ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {}", 89 ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {}",
90 params.GetBlockWidth()); 90 params.GetBlockWidth());
91 for (u32 level = 0; level < params.GetNumLevels(); ++level) { 91 for (u32 level = 0; level < params.GetNumLevels(); ++level) {
92 u8* const buffer = GetStagingBufferLevelData(level); 92 SwizzleFunc(MortonSwizzleMode::LinearToMorton, GetHostPtr(), params,
93 SwizzleFunc(MortonSwizzleMode::LinearToMorton, GetHostPtr(), params, buffer, level); 93 GetStagingBufferLevelData(level), level);
94 } 94 }
95 } else { 95 } else {
96 UNIMPLEMENTED(); 96 UNIMPLEMENTED();
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h
index d0142a9e6..eed8dc59d 100644
--- a/src/video_core/texture_cache/surface_base.h
+++ b/src/video_core/texture_cache/surface_base.h
@@ -89,14 +89,12 @@ private:
89 std::vector<u8> staging_buffer; 89 std::vector<u8> staging_buffer;
90}; 90};
91 91
92template <typename TTextureCache, typename TView, typename TExecutionContext> 92template <typename TTextureCache, typename TView>
93class SurfaceBase : public SurfaceBaseImpl { 93class SurfaceBase : public SurfaceBaseImpl {
94 static_assert(std::is_trivially_copyable_v<TExecutionContext>);
95
96public: 94public:
97 virtual TExecutionContext UploadTexture(TExecutionContext exctx) = 0; 95 virtual void UploadTexture() = 0;
98 96
99 virtual TExecutionContext DownloadTexture(TExecutionContext exctx) = 0; 97 virtual void DownloadTexture() = 0;
100 98
101 TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) { 99 TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) {
102 if (view_addr < GetGpuAddr() || !params.IsFamiliar(view_params)) { 100 if (view_addr < GetGpuAddr() || !params.IsFamiliar(view_params)) {
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index fb43fa65e..c5c01957a 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -8,7 +8,6 @@
8#include <memory> 8#include <memory>
9#include <set> 9#include <set>
10#include <tuple> 10#include <tuple>
11#include <type_traits>
12#include <unordered_map> 11#include <unordered_map>
13 12
14#include <boost/icl/interval_map.hpp> 13#include <boost/icl/interval_map.hpp>
@@ -41,11 +40,8 @@ class RasterizerInterface;
41 40
42namespace VideoCommon { 41namespace VideoCommon {
43 42
44template <typename TSurface, typename TView, typename TExecutionContext> 43template <typename TSurface, typename TView>
45class TextureCache { 44class TextureCache {
46 static_assert(std::is_trivially_copyable_v<TExecutionContext>);
47
48 using ResultType = std::tuple<TView*, TExecutionContext>;
49 using IntervalMap = boost::icl::interval_map<CacheAddr, std::set<std::shared_ptr<TSurface>>>; 45 using IntervalMap = boost::icl::interval_map<CacheAddr, std::set<std::shared_ptr<TSurface>>>;
50 using IntervalType = typename IntervalMap::interval_type; 46 using IntervalType = typename IntervalMap::interval_type;
51 47
@@ -60,37 +56,35 @@ public:
60 } 56 }
61 } 57 }
62 58
63 ResultType GetTextureSurface(TExecutionContext exctx, 59 TView* GetTextureSurface(const Tegra::Texture::FullTextureInfo& config) {
64 const Tegra::Texture::FullTextureInfo& config) {
65 const auto gpu_addr{config.tic.Address()}; 60 const auto gpu_addr{config.tic.Address()};
66 if (!gpu_addr) { 61 if (!gpu_addr) {
67 return {{}, exctx}; 62 return {};
68 } 63 }
69 const auto params{SurfaceParams::CreateForTexture(system, config)}; 64 const auto params{SurfaceParams::CreateForTexture(system, config)};
70 return GetSurfaceView(exctx, gpu_addr, params, true); 65 return GetSurfaceView(gpu_addr, params, true);
71 } 66 }
72 67
73 ResultType GetDepthBufferSurface(TExecutionContext exctx, bool preserve_contents) { 68 TView* GetDepthBufferSurface(bool preserve_contents) {
74 const auto& regs{system.GPU().Maxwell3D().regs}; 69 const auto& regs{system.GPU().Maxwell3D().regs};
75 const auto gpu_addr{regs.zeta.Address()}; 70 const auto gpu_addr{regs.zeta.Address()};
76 if (!gpu_addr || !regs.zeta_enable) { 71 if (!gpu_addr || !regs.zeta_enable) {
77 return {{}, exctx}; 72 return {};
78 } 73 }
79 const auto depth_params{SurfaceParams::CreateForDepthBuffer( 74 const auto depth_params{SurfaceParams::CreateForDepthBuffer(
80 system, regs.zeta_width, regs.zeta_height, regs.zeta.format, 75 system, regs.zeta_width, regs.zeta_height, regs.zeta.format,
81 regs.zeta.memory_layout.block_width, regs.zeta.memory_layout.block_height, 76 regs.zeta.memory_layout.block_width, regs.zeta.memory_layout.block_height,
82 regs.zeta.memory_layout.block_depth, regs.zeta.memory_layout.type)}; 77 regs.zeta.memory_layout.block_depth, regs.zeta.memory_layout.type)};
83 return GetSurfaceView(exctx, gpu_addr, depth_params, preserve_contents); 78 return GetSurfaceView(gpu_addr, depth_params, preserve_contents);
84 } 79 }
85 80
86 ResultType GetColorBufferSurface(TExecutionContext exctx, std::size_t index, 81 TView* GetColorBufferSurface(std::size_t index, bool preserve_contents) {
87 bool preserve_contents) {
88 ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets); 82 ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets);
89 83
90 const auto& regs{system.GPU().Maxwell3D().regs}; 84 const auto& regs{system.GPU().Maxwell3D().regs};
91 if (index >= regs.rt_control.count || regs.rt[index].Address() == 0 || 85 if (index >= regs.rt_control.count || regs.rt[index].Address() == 0 ||
92 regs.rt[index].format == Tegra::RenderTargetFormat::NONE) { 86 regs.rt[index].format == Tegra::RenderTargetFormat::NONE) {
93 return {{}, exctx}; 87 return {};
94 } 88 }
95 89
96 auto& memory_manager{system.GPU().MemoryManager()}; 90 auto& memory_manager{system.GPU().MemoryManager()};
@@ -98,17 +92,16 @@ public:
98 const auto gpu_addr{config.Address() + 92 const auto gpu_addr{config.Address() +
99 config.base_layer * config.layer_stride * sizeof(u32)}; 93 config.base_layer * config.layer_stride * sizeof(u32)};
100 if (!gpu_addr) { 94 if (!gpu_addr) {
101 return {{}, exctx}; 95 return {};
102 } 96 }
103 97
104 return GetSurfaceView(exctx, gpu_addr, SurfaceParams::CreateForFramebuffer(system, index), 98 return GetSurfaceView(gpu_addr, SurfaceParams::CreateForFramebuffer(system, index),
105 preserve_contents); 99 preserve_contents);
106 } 100 }
107 101
108 ResultType GetFermiSurface(TExecutionContext exctx, 102 TView* GetFermiSurface(const Tegra::Engines::Fermi2D::Regs::Surface& config) {
109 const Tegra::Engines::Fermi2D::Regs::Surface& config) { 103 return GetSurfaceView(config.Address(), SurfaceParams::CreateForFermiCopySurface(config),
110 return GetSurfaceView(exctx, config.Address(), 104 true);
111 SurfaceParams::CreateForFermiCopySurface(config), true);
112 } 105 }
113 106
114 std::shared_ptr<TSurface> TryFindFramebufferSurface(const u8* host_ptr) const { 107 std::shared_ptr<TSurface> TryFindFramebufferSurface(const u8* host_ptr) const {
@@ -126,10 +119,9 @@ protected:
126 119
127 ~TextureCache() = default; 120 ~TextureCache() = default;
128 121
129 virtual ResultType TryFastGetSurfaceView( 122 virtual TView* TryFastGetSurfaceView(
130 TExecutionContext exctx, GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr, 123 GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr, const SurfaceParams& params,
131 const SurfaceParams& params, bool preserve_contents, 124 bool preserve_contents, const std::vector<std::shared_ptr<TSurface>>& overlaps) = 0;
132 const std::vector<std::shared_ptr<TSurface>>& overlaps) = 0;
133 125
134 virtual std::shared_ptr<TSurface> CreateSurface(const SurfaceParams& params) = 0; 126 virtual std::shared_ptr<TSurface> CreateSurface(const SurfaceParams& params) = 0;
135 127
@@ -158,8 +150,7 @@ protected:
158 Core::System& system; 150 Core::System& system;
159 151
160private: 152private:
161 ResultType GetSurfaceView(TExecutionContext exctx, GPUVAddr gpu_addr, 153 TView* GetSurfaceView(GPUVAddr gpu_addr, const SurfaceParams& params, bool preserve_contents) {
162 const SurfaceParams& params, bool preserve_contents) {
163 auto& memory_manager{system.GPU().MemoryManager()}; 154 auto& memory_manager{system.GPU().MemoryManager()};
164 const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr)}; 155 const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr)};
165 DEBUG_ASSERT(cpu_addr); 156 DEBUG_ASSERT(cpu_addr);
@@ -168,18 +159,17 @@ private:
168 const auto cache_addr{ToCacheAddr(host_ptr)}; 159 const auto cache_addr{ToCacheAddr(host_ptr)};
169 auto overlaps{GetSurfacesInRegion(cache_addr, params.GetGuestSizeInBytes())}; 160 auto overlaps{GetSurfacesInRegion(cache_addr, params.GetGuestSizeInBytes())};
170 if (overlaps.empty()) { 161 if (overlaps.empty()) {
171 return LoadSurfaceView(exctx, gpu_addr, *cpu_addr, host_ptr, params, preserve_contents); 162 return LoadSurfaceView(gpu_addr, *cpu_addr, host_ptr, params, preserve_contents);
172 } 163 }
173 164
174 if (overlaps.size() == 1) { 165 if (overlaps.size() == 1) {
175 if (TView* view = overlaps[0]->TryGetView(gpu_addr, params); view) { 166 if (TView* view = overlaps[0]->TryGetView(gpu_addr, params); view) {
176 return {view, exctx}; 167 return view;
177 } 168 }
178 } 169 }
179 170
180 TView* fast_view; 171 const auto fast_view{TryFastGetSurfaceView(gpu_addr, *cpu_addr, host_ptr, params,
181 std::tie(fast_view, exctx) = TryFastGetSurfaceView(exctx, gpu_addr, *cpu_addr, host_ptr, 172 preserve_contents, overlaps)};
182 params, preserve_contents, overlaps);
183 173
184 if (!fast_view) { 174 if (!fast_view) {
185 std::sort(overlaps.begin(), overlaps.end(), [](const auto& lhs, const auto& rhs) { 175 std::sort(overlaps.begin(), overlaps.end(), [](const auto& lhs, const auto& rhs) {
@@ -191,44 +181,39 @@ private:
191 if (!fast_view) { 181 if (!fast_view) {
192 // Flush even when we don't care about the contents, to preserve memory not 182 // Flush even when we don't care about the contents, to preserve memory not
193 // written by the new surface. 183 // written by the new surface.
194 exctx = FlushSurface(exctx, surface); 184 FlushSurface(surface);
195 } 185 }
196 Unregister(surface); 186 Unregister(surface);
197 } 187 }
198
199 if (fast_view) { 188 if (fast_view) {
200 return {fast_view, exctx}; 189 return fast_view;
201 } 190 }
202 191
203 return LoadSurfaceView(exctx, gpu_addr, *cpu_addr, host_ptr, params, preserve_contents); 192 return LoadSurfaceView(gpu_addr, *cpu_addr, host_ptr, params, preserve_contents);
204 } 193 }
205 194
206 ResultType LoadSurfaceView(TExecutionContext exctx, GPUVAddr gpu_addr, VAddr cpu_addr, 195 TView* LoadSurfaceView(GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
207 u8* host_ptr, const SurfaceParams& params, bool preserve_contents) { 196 const SurfaceParams& params, bool preserve_contents) {
208 const auto new_surface{GetUncachedSurface(params)}; 197 const auto new_surface{GetUncachedSurface(params)};
209 Register(new_surface, gpu_addr, cpu_addr, host_ptr); 198 Register(new_surface, gpu_addr, cpu_addr, host_ptr);
210 if (preserve_contents) { 199 if (preserve_contents) {
211 exctx = LoadSurface(exctx, new_surface); 200 LoadSurface(new_surface);
212 } 201 }
213 return {new_surface->GetView(gpu_addr, params), exctx}; 202 return new_surface->GetView(gpu_addr, params);
214 } 203 }
215 204
216 TExecutionContext LoadSurface(TExecutionContext exctx, 205 void LoadSurface(const std::shared_ptr<TSurface>& surface) {
217 const std::shared_ptr<TSurface>& surface) {
218 surface->LoadBuffer(); 206 surface->LoadBuffer();
219 exctx = surface->UploadTexture(exctx); 207 surface->UploadTexture();
220 surface->MarkAsModified(false); 208 surface->MarkAsModified(false);
221 return exctx;
222 } 209 }
223 210
224 TExecutionContext FlushSurface(TExecutionContext exctx, 211 void FlushSurface(const std::shared_ptr<TSurface>& surface) {
225 const std::shared_ptr<TSurface>& surface) {
226 if (!surface->IsModified()) { 212 if (!surface->IsModified()) {
227 return exctx; 213 return;
228 } 214 }
229 exctx = surface->DownloadTexture(exctx); 215 surface->DownloadTexture();
230 surface->FlushBuffer(); 216 surface->FlushBuffer();
231 return exctx;
232 } 217 }
233 218
234 std::vector<std::shared_ptr<TSurface>> GetSurfacesInRegion(CacheAddr cache_addr, 219 std::vector<std::shared_ptr<TSurface>> GetSurfacesInRegion(CacheAddr cache_addr,
diff --git a/src/video_core/texture_cache/texture_cache_contextless.h b/src/video_core/texture_cache/texture_cache_contextless.h
deleted file mode 100644
index cd35a9fd4..000000000
--- a/src/video_core/texture_cache/texture_cache_contextless.h
+++ /dev/null
@@ -1,93 +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 "video_core/texture_cache/texture_cache.h"
8
9namespace VideoCommon {
10
11struct DummyExecutionContext {};
12
13template <typename TSurface, typename TView>
14class TextureCacheContextless : protected TextureCache<TSurface, TView, DummyExecutionContext> {
15 using Base = TextureCache<TSurface, TView, DummyExecutionContext>;
16
17public:
18 void InvalidateRegion(CacheAddr addr, std::size_t size) {
19 Base::InvalidateRegion(addr, size);
20 }
21
22 TView* GetTextureSurface(const Tegra::Texture::FullTextureInfo& config) {
23 return RemoveContext(Base::GetTextureSurface({}, config));
24 }
25
26 TView* GetDepthBufferSurface(bool preserve_contents) {
27 return RemoveContext(Base::GetDepthBufferSurface({}, preserve_contents));
28 }
29
30 TView* GetColorBufferSurface(std::size_t index, bool preserve_contents) {
31 return RemoveContext(Base::GetColorBufferSurface({}, index, preserve_contents));
32 }
33
34 TView* GetFermiSurface(const Tegra::Engines::Fermi2D::Regs::Surface& config) {
35 return RemoveContext(Base::GetFermiSurface({}, config));
36 }
37
38 std::shared_ptr<TSurface> TryFindFramebufferSurface(const u8* host_ptr) const {
39 return Base::TryFindFramebufferSurface(host_ptr);
40 }
41
42 u64 Tick() {
43 return Base::Tick();
44 }
45
46protected:
47 explicit TextureCacheContextless(Core::System& system,
48 VideoCore::RasterizerInterface& rasterizer)
49 : TextureCache<TSurface, TView, DummyExecutionContext>{system, rasterizer} {}
50
51 virtual TView* TryFastGetSurfaceView(
52 GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr, const SurfaceParams& params,
53 bool preserve_contents, const std::vector<std::shared_ptr<TSurface>>& overlaps) = 0;
54
55private:
56 std::tuple<TView*, DummyExecutionContext> TryFastGetSurfaceView(
57 DummyExecutionContext, GPUVAddr gpu_addr, VAddr cpu_addr, u8* host_ptr,
58 const SurfaceParams& params, bool preserve_contents,
59 const std::vector<std::shared_ptr<TSurface>>& overlaps) {
60 return {TryFastGetSurfaceView(gpu_addr, cpu_addr, host_ptr, params, preserve_contents,
61 overlaps),
62 {}};
63 }
64
65 TView* RemoveContext(std::tuple<TView*, DummyExecutionContext> return_value) {
66 const auto [view, exctx] = return_value;
67 return view;
68 }
69};
70
71template <typename TTextureCache, typename TView>
72class SurfaceBaseContextless : public SurfaceBase<TTextureCache, TView, DummyExecutionContext> {
73public:
74 DummyExecutionContext DownloadTexture(DummyExecutionContext) {
75 DownloadTextureImpl();
76 return {};
77 }
78
79 DummyExecutionContext UploadTexture(DummyExecutionContext) {
80 UploadTextureImpl();
81 return {};
82 }
83
84protected:
85 explicit SurfaceBaseContextless(TTextureCache& texture_cache, const SurfaceParams& params)
86 : SurfaceBase<TTextureCache, TView, DummyExecutionContext>{texture_cache, params} {}
87
88 virtual void DownloadTextureImpl() = 0;
89
90 virtual void UploadTextureImpl() = 0;
91};
92
93} // namespace VideoCommon