summaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-05-12 20:33:52 -0400
committerGravatar ReinUsesLisp2019-06-20 21:36:12 -0300
commit7731a0e2d15da04eea746b4b8dd5c6c4b29f9f29 (patch)
tree9769d59ddb0076234d26993ee8aca62e7da58554 /src/video_core/texture_cache
parentsurface_params: Ensure pitch is always written to avoid surface leaks (diff)
downloadyuzu-7731a0e2d15da04eea746b4b8dd5c6c4b29f9f29.tar.gz
yuzu-7731a0e2d15da04eea746b4b8dd5c6c4b29f9f29.tar.xz
yuzu-7731a0e2d15da04eea746b4b8dd5c6c4b29f9f29.zip
texture_cache: General Fixes
Fixed ASTC mipmaps loading Fixed alignment on openGL upload/download Fixed Block Height Calculation Removed unalign_height
Diffstat (limited to 'src/video_core/texture_cache')
-rw-r--r--src/video_core/texture_cache/surface_base.cpp18
-rw-r--r--src/video_core/texture_cache/surface_base.h4
-rw-r--r--src/video_core/texture_cache/surface_params.cpp52
-rw-r--r--src/video_core/texture_cache/surface_params.h27
4 files changed, 68 insertions, 33 deletions
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp
index 510d1aef5..ceff51043 100644
--- a/src/video_core/texture_cache/surface_base.cpp
+++ b/src/video_core/texture_cache/surface_base.cpp
@@ -17,6 +17,7 @@ MICROPROFILE_DEFINE(GPU_Flush_Texture, "GPU", "Texture Flush", MP_RGB(128, 192,
17 17
18using Tegra::Texture::ConvertFromGuestToHost; 18using Tegra::Texture::ConvertFromGuestToHost;
19using VideoCore::MortonSwizzleMode; 19using VideoCore::MortonSwizzleMode;
20using VideoCore::Surface::SurfaceCompression;
20 21
21SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params) 22SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params)
22 : params{params}, mipmap_sizes(params.num_levels), 23 : params{params}, mipmap_sizes(params.num_levels),
@@ -102,9 +103,20 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager,
102 } 103 }
103 } 104 }
104 105
105 for (u32 level = 0; level < params.num_levels; ++level) { 106 auto compression_type = params.GetCompressionType();
106 const std::size_t host_offset{params.GetHostMipmapLevelOffset(level)}; 107 if (compression_type == SurfaceCompression::None ||
107 ConvertFromGuestToHost(staging_buffer.data() + host_offset, params.pixel_format, 108 compression_type == SurfaceCompression::Compressed)
109 return;
110
111 for (u32 level_up = params.num_levels; level_up > 0; --level_up) {
112 const u32 level = level_up - 1;
113 const std::size_t in_host_offset{params.GetHostMipmapLevelOffset(level)};
114 const std::size_t out_host_offset = compression_type == SurfaceCompression::Rearranged
115 ? in_host_offset
116 : params.GetConvertedMipmapOffset(level);
117 u8* in_buffer = staging_buffer.data() + in_host_offset;
118 u8* out_buffer = staging_buffer.data() + out_host_offset;
119 ConvertFromGuestToHost(in_buffer, out_buffer, params.pixel_format,
108 params.GetMipWidth(level), params.GetMipHeight(level), 120 params.GetMipWidth(level), params.GetMipHeight(level),
109 params.GetMipDepth(level), true, true); 121 params.GetMipDepth(level), true, true);
110 } 122 }
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h
index 78db2d665..cb7f22706 100644
--- a/src/video_core/texture_cache/surface_base.h
+++ b/src/video_core/texture_cache/surface_base.h
@@ -93,6 +93,10 @@ public:
93 return mipmap_sizes[level]; 93 return mipmap_sizes[level];
94 } 94 }
95 95
96 bool IsLinear() const {
97 return !params.is_tiled;
98 }
99
96 bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const { 100 bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const {
97 return params.pixel_format == pixel_format; 101 return params.pixel_format == pixel_format;
98 } 102 }
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp
index 8472b69dc..d9d157d02 100644
--- a/src/video_core/texture_cache/surface_params.cpp
+++ b/src/video_core/texture_cache/surface_params.cpp
@@ -76,17 +76,14 @@ SurfaceParams SurfaceParams::CreateForTexture(Core::System& system,
76 params.type = GetFormatType(params.pixel_format); 76 params.type = GetFormatType(params.pixel_format);
77 // TODO: on 1DBuffer we should use the tic info. 77 // TODO: on 1DBuffer we should use the tic info.
78 params.target = TextureType2SurfaceTarget(entry.GetType(), entry.IsArray()); 78 params.target = TextureType2SurfaceTarget(entry.GetType(), entry.IsArray());
79 params.width = 79 params.width = config.tic.Width();
80 Common::AlignBits(config.tic.Width(), GetCompressionFactorShift(params.pixel_format)); 80 params.height = config.tic.Height();
81 params.height =
82 Common::AlignBits(config.tic.Height(), GetCompressionFactorShift(params.pixel_format));
83 params.depth = config.tic.Depth(); 81 params.depth = config.tic.Depth();
84 if (params.target == SurfaceTarget::TextureCubemap || 82 if (params.target == SurfaceTarget::TextureCubemap ||
85 params.target == SurfaceTarget::TextureCubeArray) { 83 params.target == SurfaceTarget::TextureCubeArray) {
86 params.depth *= 6; 84 params.depth *= 6;
87 } 85 }
88 params.pitch = params.is_tiled ? 0 : config.tic.Pitch(); 86 params.pitch = params.is_tiled ? 0 : config.tic.Pitch();
89 params.unaligned_height = config.tic.Height();
90 params.num_levels = config.tic.max_mip_level + 1; 87 params.num_levels = config.tic.max_mip_level + 1;
91 params.is_layered = params.IsLayered(); 88 params.is_layered = params.IsLayered();
92 return params; 89 return params;
@@ -108,7 +105,6 @@ SurfaceParams SurfaceParams::CreateForDepthBuffer(
108 params.type = GetFormatType(params.pixel_format); 105 params.type = GetFormatType(params.pixel_format);
109 params.width = zeta_width; 106 params.width = zeta_width;
110 params.height = zeta_height; 107 params.height = zeta_height;
111 params.unaligned_height = zeta_height;
112 params.target = SurfaceTarget::Texture2D; 108 params.target = SurfaceTarget::Texture2D;
113 params.depth = 1; 109 params.depth = 1;
114 params.pitch = 0; 110 params.pitch = 0;
@@ -141,7 +137,6 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz
141 } 137 }
142 params.height = config.height; 138 params.height = config.height;
143 params.depth = 1; 139 params.depth = 1;
144 params.unaligned_height = config.height;
145 params.target = SurfaceTarget::Texture2D; 140 params.target = SurfaceTarget::Texture2D;
146 params.num_levels = 1; 141 params.num_levels = 1;
147 params.is_layered = false; 142 params.is_layered = false;
@@ -164,7 +159,6 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
164 params.width = config.width; 159 params.width = config.width;
165 params.height = config.height; 160 params.height = config.height;
166 params.pitch = config.pitch; 161 params.pitch = config.pitch;
167 params.unaligned_height = config.height;
168 // TODO(Rodrigo): Try to guess the surface target from depth and layer parameters 162 // TODO(Rodrigo): Try to guess the surface target from depth and layer parameters
169 params.target = SurfaceTarget::Texture2D; 163 params.target = SurfaceTarget::Texture2D;
170 params.depth = 1; 164 params.depth = 1;
@@ -185,18 +179,18 @@ bool SurfaceParams::IsLayered() const {
185 } 179 }
186} 180}
187 181
182// Auto block resizing algorithm from:
183// https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
188u32 SurfaceParams::GetMipBlockHeight(u32 level) const { 184u32 SurfaceParams::GetMipBlockHeight(u32 level) const {
189 // Auto block resizing algorithm from:
190 // https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
191 if (level == 0) { 185 if (level == 0) {
192 return this->block_height; 186 return this->block_height;
193 } 187 }
194 188
195 const u32 height{GetMipHeight(level)}; 189 const u32 height_new{GetMipHeight(level)};
196 const u32 default_block_height{GetDefaultBlockHeight()}; 190 const u32 default_block_height{GetDefaultBlockHeight()};
197 const u32 blocks_in_y{(height + default_block_height - 1) / default_block_height}; 191 const u32 blocks_in_y{(height_new + default_block_height - 1) / default_block_height};
198 const u32 block_height = Common::Log2Ceil32(blocks_in_y); 192 const u32 block_height_new = Common::Log2Ceil32(blocks_in_y);
199 return std::clamp(block_height, 3U, 8U) - 3U; 193 return std::clamp(block_height_new, 3U, 7U) - 3U;
200} 194}
201 195
202u32 SurfaceParams::GetMipBlockDepth(u32 level) const { 196u32 SurfaceParams::GetMipBlockDepth(u32 level) const {
@@ -207,12 +201,12 @@ u32 SurfaceParams::GetMipBlockDepth(u32 level) const {
207 return 0; 201 return 0;
208 } 202 }
209 203
210 const u32 depth{GetMipDepth(level)}; 204 const u32 depth_new{GetMipDepth(level)};
211 const u32 block_depth = Common::Log2Ceil32(depth); 205 const u32 block_depth_new = Common::Log2Ceil32(depth_new);
212 if (block_depth > 4) { 206 if (block_depth_new > 4) {
213 return 5 - (GetMipBlockHeight(level) >= 2); 207 return 5 - (GetMipBlockHeight(level) >= 2);
214 } 208 }
215 return block_depth; 209 return block_depth_new;
216} 210}
217 211
218std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const { 212std::size_t SurfaceParams::GetGuestMipmapLevelOffset(u32 level) const {
@@ -231,6 +225,14 @@ std::size_t SurfaceParams::GetHostMipmapLevelOffset(u32 level) const {
231 return offset; 225 return offset;
232} 226}
233 227
228std::size_t SurfaceParams::GetConvertedMipmapOffset(u32 level) const {
229 std::size_t offset = 0;
230 for (u32 i = 0; i < level; i++) {
231 offset += GetConvertedMipmapSize(i);
232 }
233 return offset;
234}
235
234std::size_t SurfaceParams::GetGuestMipmapSize(u32 level) const { 236std::size_t SurfaceParams::GetGuestMipmapSize(u32 level) const {
235 return GetInnerMipmapMemorySize(level, false, false); 237 return GetInnerMipmapMemorySize(level, false, false);
236} 238}
@@ -239,6 +241,14 @@ std::size_t SurfaceParams::GetHostMipmapSize(u32 level) const {
239 return GetInnerMipmapMemorySize(level, true, false) * GetNumLayers(); 241 return GetInnerMipmapMemorySize(level, true, false) * GetNumLayers();
240} 242}
241 243
244std::size_t SurfaceParams::GetConvertedMipmapSize(u32 level) const {
245 constexpr std::size_t rgb8_bpp = 4ULL;
246 const std::size_t width_t = GetMipWidth(level);
247 const std::size_t height_t = GetMipHeight(level);
248 const std::size_t depth_t = is_layered ? depth : GetMipDepth(level);
249 return width_t * height_t * depth_t * rgb8_bpp;
250}
251
242std::size_t SurfaceParams::GetGuestLayerSize() const { 252std::size_t SurfaceParams::GetGuestLayerSize() const {
243 return GetLayerSize(false, false); 253 return GetLayerSize(false, false);
244} 254}
@@ -287,12 +297,10 @@ std::size_t SurfaceParams::Hash() const {
287 297
288bool SurfaceParams::operator==(const SurfaceParams& rhs) const { 298bool SurfaceParams::operator==(const SurfaceParams& rhs) const {
289 return std::tie(is_tiled, block_width, block_height, block_depth, tile_width_spacing, width, 299 return std::tie(is_tiled, block_width, block_height, block_depth, tile_width_spacing, width,
290 height, depth, pitch, unaligned_height, num_levels, pixel_format, 300 height, depth, pitch, num_levels, pixel_format, component_type, type, target) ==
291 component_type, type, target) ==
292 std::tie(rhs.is_tiled, rhs.block_width, rhs.block_height, rhs.block_depth, 301 std::tie(rhs.is_tiled, rhs.block_width, rhs.block_height, rhs.block_depth,
293 rhs.tile_width_spacing, rhs.width, rhs.height, rhs.depth, rhs.pitch, 302 rhs.tile_width_spacing, rhs.width, rhs.height, rhs.depth, rhs.pitch,
294 rhs.unaligned_height, rhs.num_levels, rhs.pixel_format, rhs.component_type, 303 rhs.num_levels, rhs.pixel_format, rhs.component_type, rhs.type, rhs.target);
295 rhs.type, rhs.target);
296} 304}
297 305
298std::string SurfaceParams::TargetName() const { 306std::string SurfaceParams::TargetName() const {
diff --git a/src/video_core/texture_cache/surface_params.h b/src/video_core/texture_cache/surface_params.h
index 7c48782c7..b3082173f 100644
--- a/src/video_core/texture_cache/surface_params.h
+++ b/src/video_core/texture_cache/surface_params.h
@@ -7,6 +7,7 @@
7#include <map> 7#include <map>
8 8
9#include "common/alignment.h" 9#include "common/alignment.h"
10#include "common/bit_util.h"
10#include "common/common_types.h" 11#include "common/common_types.h"
11#include "video_core/engines/fermi_2d.h" 12#include "video_core/engines/fermi_2d.h"
12#include "video_core/engines/maxwell_3d.h" 13#include "video_core/engines/maxwell_3d.h"
@@ -16,6 +17,8 @@
16 17
17namespace VideoCommon { 18namespace VideoCommon {
18 19
20using VideoCore::Surface::SurfaceCompression;
21
19class SurfaceParams { 22class SurfaceParams {
20public: 23public:
21 /// Creates SurfaceCachedParams from a texture configuration. 24 /// Creates SurfaceCachedParams from a texture configuration.
@@ -50,17 +53,12 @@ public:
50 53
51 std::size_t GetHostSizeInBytes() const { 54 std::size_t GetHostSizeInBytes() const {
52 std::size_t host_size_in_bytes; 55 std::size_t host_size_in_bytes;
53 if (IsPixelFormatASTC(pixel_format)) { 56 if (GetCompressionType() == SurfaceCompression::Converted) {
54 constexpr std::size_t rgb8_bpp = 4ULL; 57 constexpr std::size_t rgb8_bpp = 4ULL;
55 // ASTC is uncompressed in software, in emulated as RGBA8 58 // ASTC is uncompressed in software, in emulated as RGBA8
56 host_size_in_bytes = 0; 59 host_size_in_bytes = 0;
57 for (u32 level = 0; level < num_levels; ++level) { 60 for (u32 level = 0; level < num_levels; ++level) {
58 const std::size_t width = 61 host_size_in_bytes += GetConvertedMipmapSize(level);
59 Common::AlignUp(GetMipWidth(level), GetDefaultBlockWidth());
60 const std::size_t height =
61 Common::AlignUp(GetMipHeight(level), GetDefaultBlockHeight());
62 const std::size_t depth = is_layered ? this->depth : GetMipDepth(level);
63 host_size_in_bytes += width * height * depth * rgb8_bpp;
64 } 62 }
65 } else { 63 } else {
66 host_size_in_bytes = GetInnerMemorySize(true, false, false); 64 host_size_in_bytes = GetInnerMemorySize(true, false, false);
@@ -93,6 +91,12 @@ public:
93 /// Returns the block depth of a given mipmap level. 91 /// Returns the block depth of a given mipmap level.
94 u32 GetMipBlockDepth(u32 level) const; 92 u32 GetMipBlockDepth(u32 level) const;
95 93
94 u32 GetRowAlignment(u32 level) const {
95 const u32 bpp =
96 GetCompressionType() == SurfaceCompression::Converted ? 4 : GetBytesPerPixel();
97 return 1U << Common::CountTrailingZeroes32(GetMipWidth(level) * bpp);
98 }
99
96 // Helper used for out of class size calculations 100 // Helper used for out of class size calculations
97 static std::size_t AlignLayered(const std::size_t out_size, const u32 block_height, 101 static std::size_t AlignLayered(const std::size_t out_size, const u32 block_height,
98 const u32 block_depth) { 102 const u32 block_depth) {
@@ -106,12 +110,16 @@ public:
106 /// Returns the offset in bytes in host memory (linear) of a given mipmap level. 110 /// Returns the offset in bytes in host memory (linear) of a given mipmap level.
107 std::size_t GetHostMipmapLevelOffset(u32 level) const; 111 std::size_t GetHostMipmapLevelOffset(u32 level) const;
108 112
113 std::size_t GetConvertedMipmapOffset(u32 level) const;
114
109 /// Returns the size in bytes in guest memory of a given mipmap level. 115 /// Returns the size in bytes in guest memory of a given mipmap level.
110 std::size_t GetGuestMipmapSize(u32 level) const; 116 std::size_t GetGuestMipmapSize(u32 level) const;
111 117
112 /// Returns the size in bytes in host memory (linear) of a given mipmap level. 118 /// Returns the size in bytes in host memory (linear) of a given mipmap level.
113 std::size_t GetHostMipmapSize(u32 level) const; 119 std::size_t GetHostMipmapSize(u32 level) const;
114 120
121 std::size_t GetConvertedMipmapSize(u32 level) const;
122
115 /// Returns the size of a layer in bytes in guest memory. 123 /// Returns the size of a layer in bytes in guest memory.
116 std::size_t GetGuestLayerSize() const; 124 std::size_t GetGuestLayerSize() const;
117 125
@@ -141,6 +149,10 @@ public:
141 /// Returns true if the pixel format is a depth and/or stencil format. 149 /// Returns true if the pixel format is a depth and/or stencil format.
142 bool IsPixelFormatZeta() const; 150 bool IsPixelFormatZeta() const;
143 151
152 SurfaceCompression GetCompressionType() const {
153 return VideoCore::Surface::GetFormatCompressionType(pixel_format);
154 }
155
144 std::string TargetName() const; 156 std::string TargetName() const;
145 157
146 bool is_tiled; 158 bool is_tiled;
@@ -154,7 +166,6 @@ public:
154 u32 height; 166 u32 height;
155 u32 depth; 167 u32 depth;
156 u32 pitch; 168 u32 pitch;
157 u32 unaligned_height;
158 u32 num_levels; 169 u32 num_levels;
159 VideoCore::Surface::PixelFormat pixel_format; 170 VideoCore::Surface::PixelFormat pixel_format;
160 VideoCore::Surface::ComponentType component_type; 171 VideoCore::Surface::ComponentType component_type;