summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-05-07 10:56:45 -0400
committerGravatar ReinUsesLisp2019-06-20 21:36:12 -0300
commit3d471e732d688c20aef73a506bdb6126002d3193 (patch)
treefc10f7750306fd8b17707473b8bc1cb1624d0cda /src/video_core/texture_cache
parentAdd OGLTextureView (diff)
downloadyuzu-3d471e732d688c20aef73a506bdb6126002d3193.tar.gz
yuzu-3d471e732d688c20aef73a506bdb6126002d3193.tar.xz
yuzu-3d471e732d688c20aef73a506bdb6126002d3193.zip
Correct Surface Base and Views for new Texture Cache
Diffstat (limited to 'src/video_core/texture_cache')
-rw-r--r--src/video_core/texture_cache/copy_params.h25
-rw-r--r--src/video_core/texture_cache/surface_base.cpp108
-rw-r--r--src/video_core/texture_cache/surface_base.h297
-rw-r--r--src/video_core/texture_cache/surface_params.cpp210
-rw-r--r--src/video_core/texture_cache/surface_params.h159
-rw-r--r--src/video_core/texture_cache/surface_view.cpp12
-rw-r--r--src/video_core/texture_cache/surface_view.h35
7 files changed, 466 insertions, 380 deletions
diff --git a/src/video_core/texture_cache/copy_params.h b/src/video_core/texture_cache/copy_params.h
new file mode 100644
index 000000000..75c2b1f05
--- /dev/null
+++ b/src/video_core/texture_cache/copy_params.h
@@ -0,0 +1,25 @@
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 "common/common_types.h"
8
9namespace VideoCommon {
10
11struct CopyParams {
12 u32 source_x;
13 u32 source_y;
14 u32 source_z;
15 u32 dest_x;
16 u32 dest_y;
17 u32 dest_z;
18 u32 source_level;
19 u32 dest_level;
20 u32 width;
21 u32 height;
22 u32 depth;
23};
24
25} // namespace VideoCommon
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp
index d0779b502..5273fcb44 100644
--- a/src/video_core/texture_cache/surface_base.cpp
+++ b/src/video_core/texture_cache/surface_base.cpp
@@ -4,104 +4,120 @@
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/morton.h" 7#include "common/microprofile.h"
8#include "video_core/memory_manager.h"
8#include "video_core/texture_cache/surface_base.h" 9#include "video_core/texture_cache/surface_base.h"
9#include "video_core/texture_cache/surface_params.h" 10#include "video_core/texture_cache/surface_params.h"
10#include "video_core/textures/convert.h" 11#include "video_core/textures/convert.h"
11 12
12namespace VideoCommon { 13namespace VideoCommon {
13 14
15MICROPROFILE_DEFINE(GPU_Load_Texture, "GPU", "Texture Load", MP_RGB(128, 192, 128));
16MICROPROFILE_DEFINE(GPU_Flush_Texture, "GPU", "Texture Flush", MP_RGB(128, 192, 128));
17
14using Tegra::Texture::ConvertFromGuestToHost; 18using Tegra::Texture::ConvertFromGuestToHost;
15using VideoCore::MortonSwizzleMode; 19using VideoCore::MortonSwizzleMode;
16 20
17namespace { 21SurfaceBaseImpl::SurfaceBaseImpl(const GPUVAddr gpu_vaddr, const SurfaceParams& params)
18void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer, 22 : gpu_addr{gpu_vaddr}, params{params}, mipmap_sizes{params.num_levels},
19 u32 level) { 23 mipmap_offsets{params.num_levels}, layer_size{params.GetGuestLayerSize()},
24 memory_size{params.GetGuestSizeInBytes()}, host_memory_size{params.GetHostSizeInBytes()} {
25 u32 offset = 0;
26 mipmap_offsets.resize(params.num_levels);
27 mipmap_sizes.resize(params.num_levels);
28 gpu_addr_end = gpu_addr + memory_size;
29 for (u32 i = 0; i < params.num_levels; i++) {
30 mipmap_offsets[i] = offset;
31 mipmap_sizes[i] = params.GetGuestMipmapSize(i);
32 offset += mipmap_sizes[i];
33 }
34}
35
36void SurfaceBaseImpl::SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params,
37 u8* buffer, u32 level) {
20 const u32 width{params.GetMipWidth(level)}; 38 const u32 width{params.GetMipWidth(level)};
21 const u32 height{params.GetMipHeight(level)}; 39 const u32 height{params.GetMipHeight(level)};
22 const u32 block_height{params.GetMipBlockHeight(level)}; 40 const u32 block_height{params.GetMipBlockHeight(level)};
23 const u32 block_depth{params.GetMipBlockDepth(level)}; 41 const u32 block_depth{params.GetMipBlockDepth(level)};
24 42
25 std::size_t guest_offset{params.GetGuestMipmapLevelOffset(level)}; 43 std::size_t guest_offset{mipmap_offsets[level]};
26 if (params.IsLayered()) { 44 if (params.is_layered) {
27 std::size_t host_offset{0}; 45 std::size_t host_offset{0};
28 const std::size_t guest_stride = params.GetGuestLayerSize(); 46 const std::size_t guest_stride = layer_size;
29 const std::size_t host_stride = params.GetHostLayerSize(level); 47 const std::size_t host_stride = params.GetHostLayerSize(level);
30 for (u32 layer = 0; layer < params.GetNumLayers(); layer++) { 48 for (u32 layer = 0; layer < params.depth; layer++) {
31 MortonSwizzle(mode, params.GetPixelFormat(), width, block_height, height, block_depth, 49 MortonSwizzle(mode, params.pixel_format, width, block_height, height, block_depth, 1,
32 1, params.GetTileWidthSpacing(), buffer + host_offset, 50 params.tile_width_spacing, buffer + host_offset, memory + guest_offset);
33 memory + guest_offset);
34 guest_offset += guest_stride; 51 guest_offset += guest_stride;
35 host_offset += host_stride; 52 host_offset += host_stride;
36 } 53 }
37 } else { 54 } else {
38 MortonSwizzle(mode, params.GetPixelFormat(), width, block_height, height, block_depth, 55 MortonSwizzle(mode, params.pixel_format, width, block_height, height, block_depth,
39 params.GetMipDepth(level), params.GetTileWidthSpacing(), buffer, 56 params.GetMipDepth(level), params.tile_width_spacing, buffer,
40 memory + guest_offset); 57 memory + guest_offset);
41 } 58 }
42} 59}
43} // Anonymous namespace
44 60
45SurfaceBaseImpl::SurfaceBaseImpl(const SurfaceParams& params) : params{params} { 61void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager,
46 staging_buffer.resize(params.GetHostSizeInBytes()); 62 std::vector<u8>& staging_buffer) {
47} 63 MICROPROFILE_SCOPE(GPU_Load_Texture);
48 64 auto host_ptr = memory_manager.GetPointer(gpu_addr);
49SurfaceBaseImpl::~SurfaceBaseImpl() = default; 65 if (params.is_tiled) {
50 66 ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture target {}",
51void SurfaceBaseImpl::LoadBuffer() { 67 params.block_width, static_cast<u32>(params.target));
52 if (params.IsTiled()) { 68 for (u32 level = 0; level < params.num_levels; ++level) {
53 ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {} on texture target {}", 69 const u32 host_offset = params.GetHostMipmapLevelOffset(level);
54 params.GetBlockWidth(), static_cast<u32>(params.GetTarget()));
55 for (u32 level = 0; level < params.GetNumLevels(); ++level) {
56 SwizzleFunc(MortonSwizzleMode::MortonToLinear, host_ptr, params, 70 SwizzleFunc(MortonSwizzleMode::MortonToLinear, host_ptr, params,
57 GetStagingBufferLevelData(level), level); 71 staging_buffer.data() + host_offset, level);
58 } 72 }
59 } else { 73 } else {
60 ASSERT_MSG(params.GetNumLevels() == 1, "Linear mipmap loading is not implemented"); 74 ASSERT_MSG(params.num_levels == 1, "Linear mipmap loading is not implemented");
61 const u32 bpp{GetFormatBpp(params.GetPixelFormat()) / CHAR_BIT}; 75 const u32 bpp{params.GetBytesPerPixel()};
62 const u32 block_width{params.GetDefaultBlockWidth()}; 76 const u32 block_width{params.GetDefaultBlockWidth()};
63 const u32 block_height{params.GetDefaultBlockHeight()}; 77 const u32 block_height{params.GetDefaultBlockHeight()};
64 const u32 width{(params.GetWidth() + block_width - 1) / block_width}; 78 const u32 width{(params.width + block_width - 1) / block_width};
65 const u32 height{(params.GetHeight() + block_height - 1) / block_height}; 79 const u32 height{(params.height + block_height - 1) / block_height};
66 const u32 copy_size{width * bpp}; 80 const u32 copy_size{width * bpp};
67 if (params.GetPitch() == copy_size) { 81 if (params.pitch == copy_size) {
68 std::memcpy(staging_buffer.data(), host_ptr, params.GetHostSizeInBytes()); 82 std::memcpy(staging_buffer.data(), host_ptr, params.GetHostSizeInBytes());
69 } else { 83 } else {
70 const u8* start{host_ptr}; 84 const u8* start{host_ptr};
71 u8* write_to{staging_buffer.data()}; 85 u8* write_to{staging_buffer.data()};
72 for (u32 h = height; h > 0; --h) { 86 for (u32 h = height; h > 0; --h) {
73 std::memcpy(write_to, start, copy_size); 87 std::memcpy(write_to, start, copy_size);
74 start += params.GetPitch(); 88 start += params.pitch;
75 write_to += copy_size; 89 write_to += copy_size;
76 } 90 }
77 } 91 }
78 } 92 }
79 93
80 for (u32 level = 0; level < params.GetNumLevels(); ++level) { 94 for (u32 level = 0; level < params.num_levels; ++level) {
81 ConvertFromGuestToHost(GetStagingBufferLevelData(level), params.GetPixelFormat(), 95 const u32 host_offset = params.GetHostMipmapLevelOffset(level);
96 ConvertFromGuestToHost(staging_buffer.data() + host_offset, params.pixel_format,
82 params.GetMipWidth(level), params.GetMipHeight(level), 97 params.GetMipWidth(level), params.GetMipHeight(level),
83 params.GetMipDepth(level), true, true); 98 params.GetMipDepth(level), true, true);
84 } 99 }
85} 100}
86 101
87void SurfaceBaseImpl::FlushBuffer() { 102void SurfaceBaseImpl::FlushBuffer(std::vector<u8>& staging_buffer) {
88 if (params.IsTiled()) { 103 MICROPROFILE_SCOPE(GPU_Flush_Texture);
89 ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {}", 104 if (params.is_tiled) {
90 params.GetBlockWidth()); 105 ASSERT_MSG(params.block_width == 1, "Block width is defined as {}", params.block_width);
91 for (u32 level = 0; level < params.GetNumLevels(); ++level) { 106 for (u32 level = 0; level < params.num_levels; ++level) {
92 SwizzleFunc(MortonSwizzleMode::LinearToMorton, GetHostPtr(), params, 107 const u32 host_offset = params.GetHostMipmapLevelOffset(level);
93 GetStagingBufferLevelData(level), level); 108 SwizzleFunc(MortonSwizzleMode::LinearToMorton, host_ptr, params,
109 staging_buffer.data() + host_offset, level);
94 } 110 }
95 } else { 111 } else {
96 UNIMPLEMENTED(); 112 UNIMPLEMENTED();
97 /* 113 /*
98 ASSERT(params.GetTarget() == SurfaceTarget::Texture2D); 114 ASSERT(params.target == SurfaceTarget::Texture2D);
99 ASSERT(params.GetNumLevels() == 1); 115 ASSERT(params.num_levels == 1);
100 116
101 const u32 bpp{params.GetFormatBpp() / 8}; 117 const u32 bpp{params.GetFormatBpp() / 8};
102 const u32 copy_size{params.GetWidth() * bpp}; 118 const u32 copy_size{params.width * bpp};
103 if (params.GetPitch() == copy_size) { 119 if (params.pitch == copy_size) {
104 std::memcpy(host_ptr, staging_buffer.data(), GetSizeInBytes()); 120 std::memcpy(host_ptr, staging_buffer.data(), memory_size);
105 } else { 121 } else {
106 u8* start{host_ptr}; 122 u8* start{host_ptr};
107 const u8* read_to{staging_buffer.data()}; 123 const u8* read_to{staging_buffer.data()};
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h
index eed8dc59d..5fd7add0a 100644
--- a/src/video_core/texture_cache/surface_base.h
+++ b/src/video_core/texture_cache/surface_base.h
@@ -4,166 +4,309 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <algorithm>
7#include <unordered_map> 8#include <unordered_map>
9#include <vector>
8 10
9#include "common/assert.h" 11#include "common/assert.h"
10#include "common/common_types.h" 12#include "common/common_types.h"
11#include "video_core/gpu.h" 13#include "video_core/gpu.h"
14#include "video_core/morton.h"
15#include "video_core/texture_cache/copy_params.h"
12#include "video_core/texture_cache/surface_params.h" 16#include "video_core/texture_cache/surface_params.h"
13#include "video_core/texture_cache/surface_view.h" 17#include "video_core/texture_cache/surface_view.h"
14 18
19template<class ForwardIt, class T, class Compare=std::less<>>
20ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp={})
21{
22 // Note: BOTH type T and the type after ForwardIt is dereferenced
23 // must be implicitly convertible to BOTH Type1 and Type2, used in Compare.
24 // This is stricter than lower_bound requirement (see above)
25
26 first = std::lower_bound(first, last, value, comp);
27 return first != last && !comp(value, *first) ? first : last;
28}
29
30namespace Tegra {
31class MemoryManager;
32}
33
15namespace VideoCommon { 34namespace VideoCommon {
16 35
36using VideoCore::Surface::SurfaceTarget;
37using VideoCore::MortonSwizzleMode;
38
17class SurfaceBaseImpl { 39class SurfaceBaseImpl {
18public: 40public:
19 void LoadBuffer(); 41 void LoadBuffer(Tegra::MemoryManager& memory_manager, std::vector<u8>& staging_buffer);
20 42
21 void FlushBuffer(); 43 void FlushBuffer(std::vector<u8>& staging_buffer);
22 44
23 GPUVAddr GetGpuAddr() const { 45 GPUVAddr GetGpuAddr() const {
24 ASSERT(is_registered);
25 return gpu_addr; 46 return gpu_addr;
26 } 47 }
27 48
49 GPUVAddr GetGpuAddrEnd() const {
50 return gpu_addr_end;
51 }
52
53 bool Overlaps(const GPUVAddr start, const GPUVAddr end) const {
54 return (gpu_addr < end) && (gpu_addr_end > start);
55 }
56
57 // Use only when recycling a surface
58 void SetGpuAddr(const GPUVAddr new_addr) {
59 gpu_addr = new_addr;
60 gpu_addr_end = new_addr + memory_size;
61 }
62
28 VAddr GetCpuAddr() const { 63 VAddr GetCpuAddr() const {
29 ASSERT(is_registered); 64 return gpu_addr;
30 return cpu_addr; 65 }
66
67 void SetCpuAddr(const VAddr new_addr) {
68 cpu_addr = new_addr;
31 } 69 }
32 70
33 u8* GetHostPtr() const { 71 u8* GetHostPtr() const {
34 ASSERT(is_registered);
35 return host_ptr; 72 return host_ptr;
36 } 73 }
37 74
38 CacheAddr GetCacheAddr() const { 75 void SetHostPtr(u8* new_addr) {
39 ASSERT(is_registered); 76 host_ptr = new_addr;
40 return cache_addr;
41 } 77 }
42 78
43 const SurfaceParams& GetSurfaceParams() const { 79 const SurfaceParams& GetSurfaceParams() const {
44 return params; 80 return params;
45 } 81 }
46 82
47 void Register(GPUVAddr gpu_addr_, VAddr cpu_addr_, u8* host_ptr_) { 83 std::size_t GetSizeInBytes() const {
48 ASSERT(!is_registered); 84 return memory_size;
49 is_registered = true;
50 gpu_addr = gpu_addr_;
51 cpu_addr = cpu_addr_;
52 host_ptr = host_ptr_;
53 cache_addr = ToCacheAddr(host_ptr_);
54 DecorateSurfaceName();
55 } 85 }
56 86
57 void Unregister() { 87 std::size_t GetHostSizeInBytes() const {
58 ASSERT(is_registered); 88 return host_memory_size;
59 is_registered = false;
60 } 89 }
61 90
62 bool IsRegistered() const { 91 std::size_t GetMipmapSize(const u32 level) const {
63 return is_registered; 92 return mipmap_sizes[level];
64 } 93 }
65 94
66 std::size_t GetSizeInBytes() const { 95 bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const {
67 return params.GetGuestSizeInBytes(); 96 return params.pixel_format == pixel_format;
97 }
98
99 bool MatchTarget(VideoCore::Surface::SurfaceTarget target) const {
100 return params.target == target;
101 }
102
103 bool MatchesTopology(const SurfaceParams& rhs) const {
104 const u32 src_bpp = params.GetBytesPerPixel();
105 const u32 dst_bpp = rhs.GetBytesPerPixel();
106 return std::tie(src_bpp, params.is_tiled) == std::tie(dst_bpp, rhs.is_tiled);
107 }
108
109 bool MatchesStructure(const SurfaceParams& rhs) const {
110 if (params.is_tiled) {
111 const u32 a_width1 = params.GetBlockAlignedWidth();
112 const u32 a_width2 = rhs.GetBlockAlignedWidth();
113 return std::tie(a_width1, params.height, params.depth, params.block_width,
114 params.block_height, params.block_depth, params.tile_width_spacing) ==
115 std::tie(a_width2, rhs.height, rhs.depth, rhs.block_width, rhs.block_height,
116 rhs.block_depth, rhs.tile_width_spacing);
117 } else {
118 return std::tie(params.width, params.height, params.pitch) ==
119 std::tie(rhs.width, rhs.height, rhs.pitch);
120 }
121 }
122
123 std::optional<std::pair<u32, u32>> GetLayerMipmap(const GPUVAddr candidate_gpu_addr) const {
124 if (candidate_gpu_addr < gpu_addr)
125 return {};
126 const GPUVAddr relative_address = candidate_gpu_addr - gpu_addr;
127 const u32 layer = relative_address / layer_size;
128 const GPUVAddr mipmap_address = relative_address - layer_size * layer;
129 const auto mipmap_it = binary_find(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address);
130 if (mipmap_it != mipmap_offsets.end()) {
131 return {{layer, std::distance(mipmap_offsets.begin(), mipmap_it)}};
132 }
133 return {};
68 } 134 }
69 135
70 u8* GetStagingBufferLevelData(u32 level) { 136 std::vector<CopyParams> BreakDown() const {
71 return staging_buffer.data() + params.GetHostMipmapLevelOffset(level); 137 auto set_up_copy = [](CopyParams& cp, const SurfaceParams& params, const u32 depth,
138 const u32 level) {
139 cp.source_x = 0;
140 cp.source_y = 0;
141 cp.source_z = 0;
142 cp.dest_x = 0;
143 cp.dest_y = 0;
144 cp.dest_z = 0;
145 cp.source_level = level;
146 cp.dest_level = level;
147 cp.width = params.GetMipWidth(level);
148 cp.height = params.GetMipHeight(level);
149 cp.depth = depth;
150 };
151 const u32 layers = params.depth;
152 const u32 mipmaps = params.num_levels;
153 if (params.is_layered) {
154 std::vector<CopyParams> result{layers * mipmaps};
155 for (std::size_t layer = 0; layer < layers; layer++) {
156 const u32 layer_offset = layer * mipmaps;
157 for (std::size_t level = 0; level < mipmaps; level++) {
158 CopyParams& cp = result[layer_offset + level];
159 set_up_copy(cp, params, layer, level);
160 }
161 }
162 return result;
163 } else {
164 std::vector<CopyParams> result{mipmaps};
165 for (std::size_t level = 0; level < mipmaps; level++) {
166 CopyParams& cp = result[level];
167 set_up_copy(cp, params, params.GetMipDepth(level), level);
168 }
169 return result;
170 }
72 } 171 }
73 172
74protected: 173protected:
75 explicit SurfaceBaseImpl(const SurfaceParams& params); 174 explicit SurfaceBaseImpl(const GPUVAddr gpu_vaddr, const SurfaceParams& params);
76 ~SurfaceBaseImpl(); // non-virtual is intended 175 ~SurfaceBaseImpl() = default;
77 176
78 virtual void DecorateSurfaceName() = 0; 177 virtual void DecorateSurfaceName() = 0;
79 178
80 const SurfaceParams params; 179 const SurfaceParams params;
81
82private:
83 GPUVAddr gpu_addr{}; 180 GPUVAddr gpu_addr{};
84 VAddr cpu_addr{}; 181 GPUVAddr gpu_addr_end{};
85 u8* host_ptr{}; 182 std::vector<u32> mipmap_sizes;
86 CacheAddr cache_addr{}; 183 std::vector<u32> mipmap_offsets;
87 bool is_registered{}; 184 const std::size_t layer_size;
185 const std::size_t memory_size;
186 const std::size_t host_memory_size;
187 u8* host_ptr;
188 VAddr cpu_addr;
88 189
89 std::vector<u8> staging_buffer; 190private:
191 void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer,
192 u32 level);
90}; 193};
91 194
92template <typename TTextureCache, typename TView> 195template <typename TView>
93class SurfaceBase : public SurfaceBaseImpl { 196class SurfaceBase : public SurfaceBaseImpl {
94public: 197public:
95 virtual void UploadTexture() = 0; 198 virtual void UploadTexture(std::vector<u8>& staging_buffer) = 0;
96 199
97 virtual void DownloadTexture() = 0; 200 virtual void DownloadTexture(std::vector<u8>& staging_buffer) = 0;
98 201
99 TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) { 202 void MarkAsModified(const bool is_modified_, const u64 tick) {
100 if (view_addr < GetGpuAddr() || !params.IsFamiliar(view_params)) { 203 is_modified = is_modified_ || is_protected;
101 // It can't be a view if it's in a prior address. 204 modification_tick = tick;
102 return {}; 205 }
103 }
104 206
105 const auto relative_offset{static_cast<u64>(view_addr - GetGpuAddr())}; 207 void MarkAsProtected(const bool is_protected) {
106 const auto it{view_offset_map.find(relative_offset)}; 208 this->is_protected = is_protected;
107 if (it == view_offset_map.end()) { 209 }
108 // Couldn't find an aligned view.
109 return {};
110 }
111 const auto [layer, level] = it->second;
112 210
113 if (!params.IsViewValid(view_params, layer, level)) { 211 void MarkAsPicked(const bool is_picked) {
114 return {}; 212 this->is_picked = is_picked;
115 } 213 }
116 214
117 return GetView(layer, view_params.GetNumLayers(), level, view_params.GetNumLevels()); 215 bool IsModified() const {
216 return is_modified;
118 } 217 }
119 218
120 void MarkAsModified(bool is_modified_) { 219 bool IsProtected() const {
121 is_modified = is_modified_; 220 return is_protected;
122 if (is_modified_) {
123 modification_tick = texture_cache.Tick();
124 }
125 } 221 }
126 222
127 TView* GetView(GPUVAddr view_addr, const SurfaceParams& view_params) { 223 bool IsRegistered() const {
128 TView* view{TryGetView(view_addr, view_params)}; 224 return is_registered;
129 ASSERT(view != nullptr);
130 return view;
131 } 225 }
132 226
133 bool IsModified() const { 227 bool IsPicked() const {
134 return is_modified; 228 return is_picked;
229 }
230
231 void MarkAsRegistered(bool is_reg) {
232 is_registered = is_reg;
135 } 233 }
136 234
137 u64 GetModificationTick() const { 235 u64 GetModificationTick() const {
138 return modification_tick; 236 return modification_tick;
139 } 237 }
140 238
239 TView EmplaceOverview(const SurfaceParams& overview_params) {
240 ViewParams vp{};
241 vp.base_level = 0;
242 vp.num_levels = params.num_levels;
243 vp.target = overview_params.target;
244 if (params.is_layered && !overview_params.is_layered) {
245 vp.base_layer = 0;
246 vp.num_layers = 1;
247 } else {
248 vp.base_layer = 0;
249 vp.num_layers = params.depth;
250 }
251 return GetView(vp);
252 }
253
254 std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) {
255 if (view_addr < gpu_addr)
256 return {};
257 if (params.target == SurfaceTarget::Texture3D || view_params.target == SurfaceTarget::Texture3D) {
258 return {};
259 }
260 const std::size_t size = view_params.GetGuestSizeInBytes();
261 const GPUVAddr relative_address = view_addr - gpu_addr;
262 auto layer_mipmap = GetLayerMipmap(relative_address);
263 if (!layer_mipmap) {
264 return {};
265 }
266 const u32 layer = (*layer_mipmap).first;
267 const u32 mipmap = (*layer_mipmap).second;
268 if (GetMipmapSize(mipmap) != size) {
269 // TODO: the view may cover many mimaps, this case can still go on
270 return {};
271 }
272 ViewParams vp{};
273 vp.base_layer = layer;
274 vp.num_layers = 1;
275 vp.base_level = mipmap;
276 vp.num_levels = 1;
277 vp.target = params.target;
278 return {GetView(vp)};
279 }
280
281 TView GetMainView() const {
282 return main_view;
283 }
284
141protected: 285protected:
142 explicit SurfaceBase(TTextureCache& texture_cache, const SurfaceParams& params) 286 explicit SurfaceBase(const GPUVAddr gpu_addr, const SurfaceParams& params)
143 : SurfaceBaseImpl{params}, texture_cache{texture_cache}, 287 : SurfaceBaseImpl(gpu_addr, params) {}
144 view_offset_map{params.CreateViewOffsetMap()} {}
145 288
146 ~SurfaceBase() = default; 289 ~SurfaceBase() = default;
147 290
148 virtual std::unique_ptr<TView> CreateView(const ViewKey& view_key) = 0; 291 virtual TView CreateView(const ViewParams& view_key) = 0;
292
293 std::unordered_map<ViewParams, TView> views;
294 TView main_view;
149 295
150private: 296private:
151 TView* GetView(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels) { 297 TView GetView(const ViewParams& key) {
152 const ViewKey key{base_layer, num_layers, base_level, num_levels};
153 const auto [entry, is_cache_miss] = views.try_emplace(key); 298 const auto [entry, is_cache_miss] = views.try_emplace(key);
154 auto& view{entry->second}; 299 auto& view{entry->second};
155 if (is_cache_miss) { 300 if (is_cache_miss) {
156 view = CreateView(key); 301 view = CreateView(key);
157 } 302 }
158 return view.get(); 303 return view;
159 } 304 }
160 305
161 TTextureCache& texture_cache;
162 const std::map<u64, std::pair<u32, u32>> view_offset_map;
163
164 std::unordered_map<ViewKey, std::unique_ptr<TView>> views;
165
166 bool is_modified{}; 306 bool is_modified{};
307 bool is_protected{};
308 bool is_registered{};
309 bool is_picked{};
167 u64 modification_tick{}; 310 u64 modification_tick{};
168}; 311};
169 312
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp
index d1f8c53d5..d9052152c 100644
--- a/src/video_core/texture_cache/surface_params.cpp
+++ b/src/video_core/texture_cache/surface_params.cpp
@@ -7,6 +7,7 @@
7#include "common/cityhash.h" 7#include "common/cityhash.h"
8#include "common/alignment.h" 8#include "common/alignment.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "video_core/engines/shader_bytecode.h"
10#include "video_core/surface.h" 11#include "video_core/surface.h"
11#include "video_core/texture_cache/surface_params.h" 12#include "video_core/texture_cache/surface_params.h"
12#include "video_core/textures/decoders.h" 13#include "video_core/textures/decoders.h"
@@ -22,6 +23,37 @@ using VideoCore::Surface::PixelFormatFromTextureFormat;
22using VideoCore::Surface::SurfaceTarget; 23using VideoCore::Surface::SurfaceTarget;
23using VideoCore::Surface::SurfaceTargetFromTextureType; 24using VideoCore::Surface::SurfaceTargetFromTextureType;
24 25
26SurfaceTarget TextureType2SurfaceTarget(Tegra::Shader::TextureType type, bool is_array) {
27 switch (type) {
28 case Tegra::Shader::TextureType::Texture1D: {
29 if (is_array)
30 return SurfaceTarget::Texture1DArray;
31 else
32 return SurfaceTarget::Texture1D;
33 }
34 case Tegra::Shader::TextureType::Texture2D: {
35 if (is_array)
36 return SurfaceTarget::Texture2DArray;
37 else
38 return SurfaceTarget::Texture2D;
39 }
40 case Tegra::Shader::TextureType::Texture3D: {
41 ASSERT(!is_array);
42 return SurfaceTarget::Texture3D;
43 }
44 case Tegra::Shader::TextureType::TextureCube: {
45 if (is_array)
46 return SurfaceTarget::TextureCubeArray;
47 else
48 return SurfaceTarget::TextureCubemap;
49 }
50 default: {
51 UNREACHABLE();
52 return SurfaceTarget::Texture2D;
53 }
54 }
55}
56
25namespace { 57namespace {
26constexpr u32 GetMipmapSize(bool uncompressed, u32 mip_size, u32 tile) { 58constexpr u32 GetMipmapSize(bool uncompressed, u32 mip_size, u32 tile) {
27 return uncompressed ? mip_size : std::max(1U, (mip_size + tile - 1) / tile); 59 return uncompressed ? mip_size : std::max(1U, (mip_size + tile - 1) / tile);
@@ -29,7 +61,8 @@ constexpr u32 GetMipmapSize(bool uncompressed, u32 mip_size, u32 tile) {
29} // Anonymous namespace 61} // Anonymous namespace
30 62
31SurfaceParams SurfaceParams::CreateForTexture(Core::System& system, 63SurfaceParams SurfaceParams::CreateForTexture(Core::System& system,
32 const Tegra::Texture::FullTextureInfo& config) { 64 const Tegra::Texture::FullTextureInfo& config,
65 const VideoCommon::Shader::Sampler& entry) {
33 SurfaceParams params; 66 SurfaceParams params;
34 params.is_tiled = config.tic.IsTiled(); 67 params.is_tiled = config.tic.IsTiled();
35 params.srgb_conversion = config.tic.IsSrgbConversionEnabled(); 68 params.srgb_conversion = config.tic.IsSrgbConversionEnabled();
@@ -41,7 +74,8 @@ SurfaceParams SurfaceParams::CreateForTexture(Core::System& system,
41 params.srgb_conversion); 74 params.srgb_conversion);
42 params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value()); 75 params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value());
43 params.type = GetFormatType(params.pixel_format); 76 params.type = GetFormatType(params.pixel_format);
44 params.target = SurfaceTargetFromTextureType(config.tic.texture_type); 77 // TODO: on 1DBuffer we should use the tic info.
78 params.target = TextureType2SurfaceTarget(entry.GetType(), entry.IsArray());
45 params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); 79 params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format));
46 params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format)); 80 params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format));
47 params.depth = config.tic.Depth(); 81 params.depth = config.tic.Depth();
@@ -52,8 +86,7 @@ SurfaceParams SurfaceParams::CreateForTexture(Core::System& system,
52 params.pitch = params.is_tiled ? 0 : config.tic.Pitch(); 86 params.pitch = params.is_tiled ? 0 : config.tic.Pitch();
53 params.unaligned_height = config.tic.Height(); 87 params.unaligned_height = config.tic.Height();
54 params.num_levels = config.tic.max_mip_level + 1; 88 params.num_levels = config.tic.max_mip_level + 1;
55 89 params.is_layered = params.IsLayered();
56 params.CalculateCachedValues();
57 return params; 90 return params;
58} 91}
59 92
@@ -77,8 +110,7 @@ SurfaceParams SurfaceParams::CreateForDepthBuffer(
77 params.target = SurfaceTarget::Texture2D; 110 params.target = SurfaceTarget::Texture2D;
78 params.depth = 1; 111 params.depth = 1;
79 params.num_levels = 1; 112 params.num_levels = 1;
80 113 params.is_layered = false;
81 params.CalculateCachedValues();
82 return params; 114 return params;
83} 115}
84 116
@@ -108,8 +140,7 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz
108 params.unaligned_height = config.height; 140 params.unaligned_height = config.height;
109 params.target = SurfaceTarget::Texture2D; 141 params.target = SurfaceTarget::Texture2D;
110 params.num_levels = 1; 142 params.num_levels = 1;
111 143 params.is_layered = false;
112 params.CalculateCachedValues();
113 return params; 144 return params;
114} 145}
115 146
@@ -128,13 +159,13 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
128 params.type = GetFormatType(params.pixel_format); 159 params.type = GetFormatType(params.pixel_format);
129 params.width = config.width; 160 params.width = config.width;
130 params.height = config.height; 161 params.height = config.height;
162 params.pitch = config.pitch;
131 params.unaligned_height = config.height; 163 params.unaligned_height = config.height;
132 // TODO(Rodrigo): Try to guess the surface target from depth and layer parameters 164 // TODO(Rodrigo): Try to guess the surface target from depth and layer parameters
133 params.target = SurfaceTarget::Texture2D; 165 params.target = SurfaceTarget::Texture2D;
134 params.depth = 1; 166 params.depth = 1;
135 params.num_levels = 1; 167 params.num_levels = 1;
136 168 params.is_layered = params.IsLayered();
137 params.CalculateCachedValues();
138 return params; 169 return params;
139} 170}
140 171
@@ -147,7 +178,7 @@ u32 SurfaceParams::GetMipHeight(u32 level) const {
147} 178}
148 179
149u32 SurfaceParams::GetMipDepth(u32 level) const { 180u32 SurfaceParams::GetMipDepth(u32 level) const {
150 return IsLayered() ? depth : std::max(1U, depth >> level); 181 return is_layered ? depth : std::max(1U, depth >> level);
151} 182}
152 183
153bool SurfaceParams::IsLayered() const { 184bool SurfaceParams::IsLayered() const {
@@ -183,7 +214,7 @@ u32 SurfaceParams::GetMipBlockDepth(u32 level) const {
183 if (level == 0) { 214 if (level == 0) {
184 return this->block_depth; 215 return this->block_depth;
185 } 216 }
186 if (IsLayered()) { 217 if (is_layered) {
187 return 1; 218 return 1;
188 } 219 }
189 220
@@ -216,6 +247,10 @@ std::size_t SurfaceParams::GetHostMipmapLevelOffset(u32 level) const {
216 return offset; 247 return offset;
217} 248}
218 249
250std::size_t SurfaceParams::GetGuestMipmapSize(u32 level) const {
251 return GetInnerMipmapMemorySize(level, false, false);
252}
253
219std::size_t SurfaceParams::GetHostMipmapSize(u32 level) const { 254std::size_t SurfaceParams::GetHostMipmapSize(u32 level) const {
220 return GetInnerMipmapMemorySize(level, true, false) * GetNumLayers(); 255 return GetInnerMipmapMemorySize(level, true, false) * GetNumLayers();
221} 256}
@@ -229,7 +264,7 @@ std::size_t SurfaceParams::GetLayerSize(bool as_host_size, bool uncompressed) co
229 for (u32 level = 0; level < num_levels; ++level) { 264 for (u32 level = 0; level < num_levels; ++level) {
230 size += GetInnerMipmapMemorySize(level, as_host_size, uncompressed); 265 size += GetInnerMipmapMemorySize(level, as_host_size, uncompressed);
231 } 266 }
232 if (is_tiled && (IsLayered() || target == SurfaceTarget::Texture3D)) { 267 if (is_tiled && is_layered) {
233 return Common::AlignUp(size, Tegra::Texture::GetGOBSize() * block_height * block_depth); 268 return Common::AlignUp(size, Tegra::Texture::GetGOBSize() * block_height * block_depth);
234 } 269 }
235 return size; 270 return size;
@@ -256,150 +291,32 @@ u32 SurfaceParams::GetBytesPerPixel() const {
256 return VideoCore::Surface::GetBytesPerPixel(pixel_format); 291 return VideoCore::Surface::GetBytesPerPixel(pixel_format);
257} 292}
258 293
259bool SurfaceParams::IsFamiliar(const SurfaceParams& view_params) const {
260 if (std::tie(is_tiled, tile_width_spacing, pixel_format, component_type, type) !=
261 std::tie(view_params.is_tiled, view_params.tile_width_spacing, view_params.pixel_format,
262 view_params.component_type, view_params.type)) {
263 return false;
264 }
265
266 const SurfaceTarget view_target{view_params.target};
267 if (view_target == target) {
268 return true;
269 }
270
271 switch (target) {
272 case SurfaceTarget::Texture1D:
273 case SurfaceTarget::Texture2D:
274 case SurfaceTarget::Texture3D:
275 return false;
276 case SurfaceTarget::Texture1DArray:
277 return view_target == SurfaceTarget::Texture1D;
278 case SurfaceTarget::Texture2DArray:
279 return view_target == SurfaceTarget::Texture2D;
280 case SurfaceTarget::TextureCubemap:
281 return view_target == SurfaceTarget::Texture2D ||
282 view_target == SurfaceTarget::Texture2DArray;
283 case SurfaceTarget::TextureCubeArray:
284 return view_target == SurfaceTarget::Texture2D ||
285 view_target == SurfaceTarget::Texture2DArray ||
286 view_target == SurfaceTarget::TextureCubemap;
287 default:
288 UNIMPLEMENTED_MSG("Unimplemented texture family={}", static_cast<u32>(target));
289 return false;
290 }
291}
292
293bool SurfaceParams::IsPixelFormatZeta() const { 294bool SurfaceParams::IsPixelFormatZeta() const {
294 return pixel_format >= VideoCore::Surface::PixelFormat::MaxColorFormat && 295 return pixel_format >= VideoCore::Surface::PixelFormat::MaxColorFormat &&
295 pixel_format < VideoCore::Surface::PixelFormat::MaxDepthStencilFormat; 296 pixel_format < VideoCore::Surface::PixelFormat::MaxDepthStencilFormat;
296} 297}
297 298
298void SurfaceParams::CalculateCachedValues() {
299 switch (target) {
300 case SurfaceTarget::Texture1D:
301 case SurfaceTarget::Texture2D:
302 case SurfaceTarget::Texture3D:
303 num_layers = 1;
304 break;
305 case SurfaceTarget::Texture1DArray:
306 case SurfaceTarget::Texture2DArray:
307 case SurfaceTarget::TextureCubemap:
308 case SurfaceTarget::TextureCubeArray:
309 num_layers = depth;
310 break;
311 default:
312 UNREACHABLE();
313 }
314
315 guest_size_in_bytes = GetInnerMemorySize(false, false, false);
316
317 if (IsPixelFormatASTC(pixel_format)) {
318 // ASTC is uncompressed in software, in emulated as RGBA8
319 host_size_in_bytes = static_cast<std::size_t>(width) * static_cast<std::size_t>(height) *
320 static_cast<std::size_t>(depth) * 4ULL;
321 } else {
322 host_size_in_bytes = GetInnerMemorySize(true, false, false);
323 }
324}
325
326std::size_t SurfaceParams::GetInnerMipmapMemorySize(u32 level, bool as_host_size, 299std::size_t SurfaceParams::GetInnerMipmapMemorySize(u32 level, bool as_host_size,
327 bool uncompressed) const { 300 bool uncompressed) const {
328 const bool tiled{as_host_size ? false : is_tiled}; 301 const bool tiled{as_host_size ? false : is_tiled};
329 const u32 width{GetMipmapSize(uncompressed, GetMipWidth(level), GetDefaultBlockWidth())}; 302 const u32 width{GetMipmapSize(uncompressed, GetMipWidth(level), GetDefaultBlockWidth())};
330 const u32 height{GetMipmapSize(uncompressed, GetMipHeight(level), GetDefaultBlockHeight())}; 303 const u32 height{GetMipmapSize(uncompressed, GetMipHeight(level), GetDefaultBlockHeight())};
331 const u32 depth{target == SurfaceTarget::Texture3D ? GetMipDepth(level) : 1U}; 304 const u32 depth{is_layered ? 1U : GetMipDepth(level)};
332 return Tegra::Texture::CalculateSize(tiled, GetBytesPerPixel(), width, height, depth, 305 return Tegra::Texture::CalculateSize(tiled, GetBytesPerPixel(), width, height, depth,
333 GetMipBlockHeight(level), GetMipBlockDepth(level)); 306 GetMipBlockHeight(level), GetMipBlockDepth(level));
334} 307}
335 308
336std::size_t SurfaceParams::GetInnerMemorySize(bool as_host_size, bool layer_only, 309std::size_t SurfaceParams::GetInnerMemorySize(bool as_host_size, bool layer_only,
337 bool uncompressed) const { 310 bool uncompressed) const {
338 return GetLayerSize(as_host_size, uncompressed) * (layer_only ? 1U : num_layers); 311 return GetLayerSize(as_host_size, uncompressed) * (layer_only ? 1U : depth);
339}
340
341std::map<u64, std::pair<u32, u32>> SurfaceParams::CreateViewOffsetMap() const {
342 std::map<u64, std::pair<u32, u32>> view_offset_map;
343 switch (target) {
344 case SurfaceTarget::Texture1D:
345 case SurfaceTarget::Texture2D:
346 case SurfaceTarget::Texture3D: {
347 // TODO(Rodrigo): Add layer iterations for 3D textures
348 constexpr u32 layer = 0;
349 for (u32 level = 0; level < num_levels; ++level) {
350 const std::size_t offset{GetGuestMipmapLevelOffset(level)};
351 view_offset_map.insert({offset, {layer, level}});
352 }
353 break;
354 }
355 case SurfaceTarget::Texture1DArray:
356 case SurfaceTarget::Texture2DArray:
357 case SurfaceTarget::TextureCubemap:
358 case SurfaceTarget::TextureCubeArray: {
359 const std::size_t layer_size{GetGuestLayerSize()};
360 for (u32 level = 0; level < num_levels; ++level) {
361 const std::size_t level_offset{GetGuestMipmapLevelOffset(level)};
362 for (u32 layer = 0; layer < num_layers; ++layer) {
363 const auto layer_offset{static_cast<std::size_t>(layer_size * layer)};
364 const std::size_t offset{level_offset + layer_offset};
365 view_offset_map.insert({offset, {layer, level}});
366 }
367 }
368 break;
369 }
370 default:
371 UNIMPLEMENTED_MSG("Unimplemented surface target {}", static_cast<u32>(target));
372 }
373 return view_offset_map;
374}
375
376bool SurfaceParams::IsViewValid(const SurfaceParams& view_params, u32 layer, u32 level) const {
377 return IsDimensionValid(view_params, level) && IsDepthValid(view_params, level) &&
378 IsInBounds(view_params, layer, level);
379} 312}
380 313
381bool SurfaceParams::IsDimensionValid(const SurfaceParams& view_params, u32 level) const { 314std::size_t SurfaceParams::Hash() const {
382 return view_params.width == GetMipWidth(level) && view_params.height == GetMipHeight(level);
383}
384
385bool SurfaceParams::IsDepthValid(const SurfaceParams& view_params, u32 level) const {
386 if (view_params.target != SurfaceTarget::Texture3D) {
387 return true;
388 }
389 return view_params.depth == GetMipDepth(level);
390}
391
392bool SurfaceParams::IsInBounds(const SurfaceParams& view_params, u32 layer, u32 level) const {
393 return layer + view_params.num_layers <= num_layers &&
394 level + view_params.num_levels <= num_levels;
395}
396
397std::size_t HasheableSurfaceParams::Hash() const {
398 return static_cast<std::size_t>( 315 return static_cast<std::size_t>(
399 Common::CityHash64(reinterpret_cast<const char*>(this), sizeof(*this))); 316 Common::CityHash64(reinterpret_cast<const char*>(this), sizeof(*this)));
400} 317}
401 318
402bool HasheableSurfaceParams::operator==(const HasheableSurfaceParams& rhs) const { 319bool SurfaceParams::operator==(const SurfaceParams& rhs) const {
403 return std::tie(is_tiled, block_width, block_height, block_depth, tile_width_spacing, width, 320 return std::tie(is_tiled, block_width, block_height, block_depth, tile_width_spacing, width,
404 height, depth, pitch, unaligned_height, num_levels, pixel_format, 321 height, depth, pitch, unaligned_height, num_levels, pixel_format,
405 component_type, type, target) == 322 component_type, type, target) ==
@@ -409,4 +326,27 @@ bool HasheableSurfaceParams::operator==(const HasheableSurfaceParams& rhs) const
409 rhs.type, rhs.target); 326 rhs.type, rhs.target);
410} 327}
411 328
329std::string SurfaceParams::TargetName() const {
330 switch (target) {
331 case SurfaceTarget::Texture1D:
332 return "1D";
333 case SurfaceTarget::Texture2D:
334 return "2D";
335 case SurfaceTarget::Texture3D:
336 return "3D";
337 case SurfaceTarget::Texture1DArray:
338 return "1DArray";
339 case SurfaceTarget::Texture2DArray:
340 return "2DArray";
341 case SurfaceTarget::TextureCubemap:
342 return "Cube";
343 case SurfaceTarget::TextureCubeArray:
344 return "CubeArray";
345 default:
346 LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target));
347 UNREACHABLE();
348 return fmt::format("TUK({})", static_cast<u32>(target));
349 }
350}
351
412} // namespace VideoCommon 352} // namespace VideoCommon
diff --git a/src/video_core/texture_cache/surface_params.h b/src/video_core/texture_cache/surface_params.h
index 77dc0ba66..ec8efa210 100644
--- a/src/video_core/texture_cache/surface_params.h
+++ b/src/video_core/texture_cache/surface_params.h
@@ -6,50 +6,21 @@
6 6
7#include <map> 7#include <map>
8 8
9#include "common/alignment.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "video_core/engines/fermi_2d.h" 11#include "video_core/engines/fermi_2d.h"
11#include "video_core/engines/maxwell_3d.h" 12#include "video_core/engines/maxwell_3d.h"
12#include "video_core/surface.h" 13#include "video_core/surface.h"
14#include "video_core/shader/shader_ir.h"
13 15
14namespace VideoCommon { 16namespace VideoCommon {
15 17
16class HasheableSurfaceParams { 18class SurfaceParams {
17public:
18 std::size_t Hash() const;
19
20 bool operator==(const HasheableSurfaceParams& rhs) const;
21
22 bool operator!=(const HasheableSurfaceParams& rhs) const {
23 return !operator==(rhs);
24 }
25
26protected:
27 // Avoid creation outside of a managed environment.
28 HasheableSurfaceParams() = default;
29
30 bool is_tiled;
31 bool srgb_conversion;
32 u32 block_width;
33 u32 block_height;
34 u32 block_depth;
35 u32 tile_width_spacing;
36 u32 width;
37 u32 height;
38 u32 depth;
39 u32 pitch;
40 u32 unaligned_height;
41 u32 num_levels;
42 VideoCore::Surface::PixelFormat pixel_format;
43 VideoCore::Surface::ComponentType component_type;
44 VideoCore::Surface::SurfaceType type;
45 VideoCore::Surface::SurfaceTarget target;
46};
47
48class SurfaceParams final : public HasheableSurfaceParams {
49public: 19public:
50 /// Creates SurfaceCachedParams from a texture configuration. 20 /// Creates SurfaceCachedParams from a texture configuration.
51 static SurfaceParams CreateForTexture(Core::System& system, 21 static SurfaceParams CreateForTexture(Core::System& system,
52 const Tegra::Texture::FullTextureInfo& config); 22 const Tegra::Texture::FullTextureInfo& config,
23 const VideoCommon::Shader::Sampler& entry);
53 24
54 /// Creates SurfaceCachedParams for a depth buffer configuration. 25 /// Creates SurfaceCachedParams for a depth buffer configuration.
55 static SurfaceParams CreateForDepthBuffer( 26 static SurfaceParams CreateForDepthBuffer(
@@ -64,68 +35,33 @@ public:
64 static SurfaceParams CreateForFermiCopySurface( 35 static SurfaceParams CreateForFermiCopySurface(
65 const Tegra::Engines::Fermi2D::Regs::Surface& config); 36 const Tegra::Engines::Fermi2D::Regs::Surface& config);
66 37
67 bool IsTiled() const { 38 std::size_t Hash() const;
68 return is_tiled;
69 }
70
71 bool GetSrgbConversion() const {
72 return srgb_conversion;
73 }
74
75 u32 GetBlockWidth() const {
76 return block_width;
77 }
78
79 u32 GetTileWidthSpacing() const {
80 return tile_width_spacing;
81 }
82
83 u32 GetWidth() const {
84 return width;
85 }
86
87 u32 GetHeight() const {
88 return height;
89 }
90
91 u32 GetDepth() const {
92 return depth;
93 }
94
95 u32 GetPitch() const {
96 return pitch;
97 }
98
99 u32 GetNumLevels() const {
100 return num_levels;
101 }
102
103 VideoCore::Surface::PixelFormat GetPixelFormat() const {
104 return pixel_format;
105 }
106
107 VideoCore::Surface::ComponentType GetComponentType() const {
108 return component_type;
109 }
110 39
111 VideoCore::Surface::SurfaceTarget GetTarget() const { 40 bool operator==(const SurfaceParams& rhs) const;
112 return target;
113 }
114 41
115 VideoCore::Surface::SurfaceType GetType() const { 42 bool operator!=(const SurfaceParams& rhs) const {
116 return type; 43 return !operator==(rhs);
117 } 44 }
118 45
119 std::size_t GetGuestSizeInBytes() const { 46 std::size_t GetGuestSizeInBytes() const {
120 return guest_size_in_bytes; 47 return GetInnerMemorySize(false, false, false);
121 } 48 }
122 49
123 std::size_t GetHostSizeInBytes() const { 50 std::size_t GetHostSizeInBytes() const {
51 std::size_t host_size_in_bytes;
52 if (IsPixelFormatASTC(pixel_format)) {
53 // ASTC is uncompressed in software, in emulated as RGBA8
54 host_size_in_bytes = static_cast<std::size_t>(Common::AlignUp(width, GetDefaultBlockWidth())) *
55 static_cast<std::size_t>(Common::AlignUp(height, GetDefaultBlockHeight())) *
56 static_cast<std::size_t>(depth) * 4ULL;
57 } else {
58 host_size_in_bytes = GetInnerMemorySize(true, false, false);
59 }
124 return host_size_in_bytes; 60 return host_size_in_bytes;
125 } 61 }
126 62
127 u32 GetNumLayers() const { 63 u32 GetBlockAlignedWidth() const {
128 return num_layers; 64 return Common::AlignUp(width, 64 / GetBytesPerPixel());
129 } 65 }
130 66
131 /// Returns the width of a given mipmap level. 67 /// Returns the width of a given mipmap level.
@@ -137,9 +73,6 @@ public:
137 /// Returns the depth of a given mipmap level. 73 /// Returns the depth of a given mipmap level.
138 u32 GetMipDepth(u32 level) const; 74 u32 GetMipDepth(u32 level) const;
139 75
140 /// Returns true if these parameters are from a layered surface.
141 bool IsLayered() const;
142
143 /// Returns the block height of a given mipmap level. 76 /// Returns the block height of a given mipmap level.
144 u32 GetMipBlockHeight(u32 level) const; 77 u32 GetMipBlockHeight(u32 level) const;
145 78
@@ -152,6 +85,9 @@ public:
152 /// Returns the offset in bytes in host memory (linear) of a given mipmap level. 85 /// Returns the offset in bytes in host memory (linear) of a given mipmap level.
153 std::size_t GetHostMipmapLevelOffset(u32 level) const; 86 std::size_t GetHostMipmapLevelOffset(u32 level) const;
154 87
88 /// Returns the size in bytes in guest memory of a given mipmap level.
89 std::size_t GetGuestMipmapSize(u32 level) const;
90
155 /// Returns the size in bytes in host memory (linear) of a given mipmap level. 91 /// Returns the size in bytes in host memory (linear) of a given mipmap level.
156 std::size_t GetHostMipmapSize(u32 level) const; 92 std::size_t GetHostMipmapSize(u32 level) const;
157 93
@@ -173,24 +109,30 @@ public:
173 /// Returns the bytes per pixel. 109 /// Returns the bytes per pixel.
174 u32 GetBytesPerPixel() const; 110 u32 GetBytesPerPixel() const;
175 111
176 /// Returns true if another surface can be familiar with this. This is a loosely defined term
177 /// that reflects the possibility of these two surface parameters potentially being part of a
178 /// bigger superset.
179 bool IsFamiliar(const SurfaceParams& view_params) const;
180
181 /// Returns true if the pixel format is a depth and/or stencil format. 112 /// Returns true if the pixel format is a depth and/or stencil format.
182 bool IsPixelFormatZeta() const; 113 bool IsPixelFormatZeta() const;
183 114
184 /// Creates a map that redirects an address difference to a layer and mipmap level. 115 std::string TargetName() const;
185 std::map<u64, std::pair<u32, u32>> CreateViewOffsetMap() const;
186 116
187 /// Returns true if the passed surface view parameters is equal or a valid subset of this. 117 bool is_tiled;
188 bool IsViewValid(const SurfaceParams& view_params, u32 layer, u32 level) const; 118 bool srgb_conversion;
119 bool is_layered;
120 u32 block_width;
121 u32 block_height;
122 u32 block_depth;
123 u32 tile_width_spacing;
124 u32 width;
125 u32 height;
126 u32 depth;
127 u32 pitch;
128 u32 unaligned_height;
129 u32 num_levels;
130 VideoCore::Surface::PixelFormat pixel_format;
131 VideoCore::Surface::ComponentType component_type;
132 VideoCore::Surface::SurfaceType type;
133 VideoCore::Surface::SurfaceTarget target;
189 134
190private: 135private:
191 /// Calculates values that can be deduced from HasheableSurfaceParams.
192 void CalculateCachedValues();
193
194 /// Returns the size of a given mipmap level inside a layer. 136 /// Returns the size of a given mipmap level inside a layer.
195 std::size_t GetInnerMipmapMemorySize(u32 level, bool as_host_size, bool uncompressed) const; 137 std::size_t GetInnerMipmapMemorySize(u32 level, bool as_host_size, bool uncompressed) const;
196 138
@@ -200,19 +142,12 @@ private:
200 /// Returns the size of a layer 142 /// Returns the size of a layer
201 std::size_t GetLayerSize(bool as_host_size, bool uncompressed) const; 143 std::size_t GetLayerSize(bool as_host_size, bool uncompressed) const;
202 144
203 /// Returns true if the passed view width and height match the size of this params in a given 145 std::size_t GetNumLayers() const {
204 /// mipmap level. 146 return is_layered ? depth : 1;
205 bool IsDimensionValid(const SurfaceParams& view_params, u32 level) const; 147 }
206
207 /// Returns true if the passed view depth match the size of this params in a given mipmap level.
208 bool IsDepthValid(const SurfaceParams& view_params, u32 level) const;
209
210 /// Returns true if the passed view layers and mipmap levels are in bounds.
211 bool IsInBounds(const SurfaceParams& view_params, u32 layer, u32 level) const;
212 148
213 std::size_t guest_size_in_bytes; 149 /// Returns true if these parameters are from a layered surface.
214 std::size_t host_size_in_bytes; 150 bool IsLayered() const;
215 u32 num_layers;
216}; 151};
217 152
218} // namespace VideoCommon 153} // namespace VideoCommon
diff --git a/src/video_core/texture_cache/surface_view.cpp b/src/video_core/texture_cache/surface_view.cpp
index 5f4cdbb1c..467696a4c 100644
--- a/src/video_core/texture_cache/surface_view.cpp
+++ b/src/video_core/texture_cache/surface_view.cpp
@@ -9,15 +9,15 @@
9 9
10namespace VideoCommon { 10namespace VideoCommon {
11 11
12std::size_t ViewKey::Hash() const { 12std::size_t ViewParams::Hash() const {
13 return static_cast<std::size_t>(base_layer) ^ static_cast<std::size_t>(num_layers << 16) ^ 13 return static_cast<std::size_t>(base_layer) ^ static_cast<std::size_t>(num_layers << 16) ^
14 (static_cast<std::size_t>(base_level) << 32) ^ 14 (static_cast<std::size_t>(base_level) << 24) ^
15 (static_cast<std::size_t>(num_levels) << 48); 15 (static_cast<std::size_t>(num_levels) << 32) ^ (static_cast<std::size_t>(target) << 36);
16} 16}
17 17
18bool ViewKey::operator==(const ViewKey& rhs) const { 18bool ViewParams::operator==(const ViewParams& rhs) const {
19 return std::tie(base_layer, num_layers, base_level, num_levels) == 19 return std::tie(base_layer, num_layers, base_level, num_levels, target) ==
20 std::tie(rhs.base_layer, rhs.num_layers, rhs.base_level, rhs.num_levels); 20 std::tie(rhs.base_layer, rhs.num_layers, rhs.base_level, rhs.num_levels, rhs.target);
21} 21}
22 22
23} // namespace VideoCommon 23} // namespace VideoCommon
diff --git a/src/video_core/texture_cache/surface_view.h b/src/video_core/texture_cache/surface_view.h
index e73d8f6ae..c122800a6 100644
--- a/src/video_core/texture_cache/surface_view.h
+++ b/src/video_core/texture_cache/surface_view.h
@@ -7,18 +7,45 @@
7#include <functional> 7#include <functional>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "video_core/surface.h"
11#include "video_core/texture_cache/surface_params.h"
10 12
11namespace VideoCommon { 13namespace VideoCommon {
12 14
13struct ViewKey { 15struct ViewParams {
14 std::size_t Hash() const; 16 std::size_t Hash() const;
15 17
16 bool operator==(const ViewKey& rhs) const; 18 bool operator==(const ViewParams& rhs) const;
17 19
18 u32 base_layer{}; 20 u32 base_layer{};
19 u32 num_layers{}; 21 u32 num_layers{};
20 u32 base_level{}; 22 u32 base_level{};
21 u32 num_levels{}; 23 u32 num_levels{};
24 VideoCore::Surface::SurfaceTarget target;
25 bool IsLayered() const {
26 switch (target) {
27 case VideoCore::Surface::SurfaceTarget::Texture1DArray:
28 case VideoCore::Surface::SurfaceTarget::Texture2DArray:
29 case VideoCore::Surface::SurfaceTarget::TextureCubemap:
30 case VideoCore::Surface::SurfaceTarget::TextureCubeArray:
31 return true;
32 default:
33 return false;
34 }
35 }
36};
37
38class ViewBase {
39public:
40 ViewBase(const ViewParams& params) : params{params} {}
41 ~ViewBase() = default;
42
43 const ViewParams& GetViewParams() const {
44 return params;
45 }
46
47protected:
48 ViewParams params;
22}; 49};
23 50
24} // namespace VideoCommon 51} // namespace VideoCommon
@@ -26,8 +53,8 @@ struct ViewKey {
26namespace std { 53namespace std {
27 54
28template <> 55template <>
29struct hash<VideoCommon::ViewKey> { 56struct hash<VideoCommon::ViewParams> {
30 std::size_t operator()(const VideoCommon::ViewKey& k) const noexcept { 57 std::size_t operator()(const VideoCommon::ViewParams& k) const noexcept {
31 return k.Hash(); 58 return k.Hash();
32 } 59 }
33}; 60};