diff options
| author | 2019-04-24 02:45:03 -0300 | |
|---|---|---|
| committer | 2019-06-20 21:36:11 -0300 | |
| commit | 5f3aacdc3760f0e9e0daeda3ee4c55e42fc9397e (patch) | |
| tree | 6c95776e1de8c347544745df1784424cafaeb414 /src | |
| parent | texture_cache: Flush 3D textures in the order they are drawn (diff) | |
| download | yuzu-5f3aacdc3760f0e9e0daeda3ee4c55e42fc9397e.tar.gz yuzu-5f3aacdc3760f0e9e0daeda3ee4c55e42fc9397e.tar.xz yuzu-5f3aacdc3760f0e9e0daeda3ee4c55e42fc9397e.zip | |
texture_cache: Move staging buffer into a generic implementation
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 114 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 7 | ||||
| -rw-r--r-- | src/video_core/texture_cache.cpp | 110 | ||||
| -rw-r--r-- | src/video_core/texture_cache.h | 161 |
4 files changed, 211 insertions, 181 deletions
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 362f4019c..3e2a1f53c 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | 15 | ||
| 16 | namespace OpenGL { | 16 | namespace OpenGL { |
| 17 | 17 | ||
| 18 | using Tegra::Texture::ConvertFromGuestToHost; | ||
| 19 | using Tegra::Texture::SwizzleSource; | 18 | using Tegra::Texture::SwizzleSource; |
| 20 | using VideoCore::MortonSwizzleMode; | 19 | using VideoCore::MortonSwizzleMode; |
| 21 | 20 | ||
| @@ -207,32 +206,6 @@ OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum inte | |||
| 207 | return texture; | 206 | return texture; |
| 208 | } | 207 | } |
| 209 | 208 | ||
| 210 | void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer, | ||
| 211 | u32 level) { | ||
| 212 | const u32 width{params.GetMipWidth(level)}; | ||
| 213 | const u32 height{params.GetMipHeight(level)}; | ||
| 214 | const u32 block_height{params.GetMipBlockHeight(level)}; | ||
| 215 | const u32 block_depth{params.GetMipBlockDepth(level)}; | ||
| 216 | |||
| 217 | std::size_t guest_offset{params.GetGuestMipmapLevelOffset(level)}; | ||
| 218 | if (params.IsLayered()) { | ||
| 219 | std::size_t host_offset{0}; | ||
| 220 | const std::size_t guest_stride = params.GetGuestLayerSize(); | ||
| 221 | const std::size_t host_stride = params.GetHostLayerSize(level); | ||
| 222 | for (u32 layer = 0; layer < params.GetNumLayers(); layer++) { | ||
| 223 | MortonSwizzle(mode, params.GetPixelFormat(), width, block_height, height, block_depth, | ||
| 224 | 1, params.GetTileWidthSpacing(), buffer + host_offset, | ||
| 225 | memory + guest_offset); | ||
| 226 | guest_offset += guest_stride; | ||
| 227 | host_offset += host_stride; | ||
| 228 | } | ||
| 229 | } else { | ||
| 230 | MortonSwizzle(mode, params.GetPixelFormat(), width, block_height, height, block_depth, | ||
| 231 | params.GetMipDepth(level), params.GetTileWidthSpacing(), buffer, | ||
| 232 | memory + guest_offset); | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | } // Anonymous namespace | 209 | } // Anonymous namespace |
| 237 | 210 | ||
| 238 | CachedSurface::CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params) | 211 | CachedSurface::CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params) |
| @@ -245,54 +218,11 @@ CachedSurface::CachedSurface(TextureCacheOpenGL& texture_cache, const SurfacePar | |||
| 245 | is_compressed = tuple.compressed; | 218 | is_compressed = tuple.compressed; |
| 246 | target = GetTextureTarget(params); | 219 | target = GetTextureTarget(params); |
| 247 | texture = CreateTexture(params, target, internal_format); | 220 | texture = CreateTexture(params, target, internal_format); |
| 248 | staging_buffer.resize(params.GetHostSizeInBytes()); | ||
| 249 | } | 221 | } |
| 250 | 222 | ||
| 251 | CachedSurface::~CachedSurface() = default; | 223 | CachedSurface::~CachedSurface() = default; |
| 252 | 224 | ||
| 253 | void CachedSurface::LoadBuffer() { | 225 | void CachedSurface::DownloadTextureImpl() { |
| 254 | if (params.IsTiled()) { | ||
| 255 | ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {} on texture target {}", | ||
| 256 | params.GetBlockWidth(), static_cast<u32>(params.GetTarget())); | ||
| 257 | for (u32 level = 0; level < params.GetNumLevels(); ++level) { | ||
| 258 | u8* const buffer{staging_buffer.data() + params.GetHostMipmapLevelOffset(level)}; | ||
| 259 | SwizzleFunc(MortonSwizzleMode::MortonToLinear, GetHostPtr(), params, buffer, level); | ||
| 260 | } | ||
| 261 | } else { | ||
| 262 | ASSERT_MSG(params.GetNumLevels() == 1, "Linear mipmap loading is not implemented"); | ||
| 263 | const u32 bpp{GetFormatBpp(params.GetPixelFormat()) / CHAR_BIT}; | ||
| 264 | const u32 block_width{VideoCore::Surface::GetDefaultBlockWidth(params.GetPixelFormat())}; | ||
| 265 | const u32 block_height{VideoCore::Surface::GetDefaultBlockHeight(params.GetPixelFormat())}; | ||
| 266 | const u32 width{(params.GetWidth() + block_width - 1) / block_width}; | ||
| 267 | const u32 height{(params.GetHeight() + block_height - 1) / block_height}; | ||
| 268 | const u32 copy_size{width * bpp}; | ||
| 269 | if (params.GetPitch() == copy_size) { | ||
| 270 | std::memcpy(staging_buffer.data(), GetHostPtr(), params.GetHostSizeInBytes()); | ||
| 271 | } else { | ||
| 272 | const u8* start{GetHostPtr()}; | ||
| 273 | u8* write_to{staging_buffer.data()}; | ||
| 274 | for (u32 h = height; h > 0; --h) { | ||
| 275 | std::memcpy(write_to, start, copy_size); | ||
| 276 | start += params.GetPitch(); | ||
| 277 | write_to += copy_size; | ||
| 278 | } | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | for (u32 level = 0; level < params.GetNumLevels(); ++level) { | ||
| 283 | ConvertFromGuestToHost(staging_buffer.data() + params.GetHostMipmapLevelOffset(level), | ||
| 284 | params.GetPixelFormat(), params.GetMipWidth(level), | ||
| 285 | params.GetMipHeight(level), params.GetMipDepth(level), true, true); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | void CachedSurface::FlushBufferImpl() { | ||
| 290 | LOG_CRITICAL(Render_OpenGL, "Flushing"); | ||
| 291 | |||
| 292 | if (!IsModified()) { | ||
| 293 | return; | ||
| 294 | } | ||
| 295 | |||
| 296 | // TODO(Rodrigo): Optimize alignment | 226 | // TODO(Rodrigo): Optimize alignment |
| 297 | glPixelStorei(GL_PACK_ALIGNMENT, 1); | 227 | glPixelStorei(GL_PACK_ALIGNMENT, 1); |
| 298 | SCOPE_EXIT({ glPixelStorei(GL_PACK_ROW_LENGTH, 0); }); | 228 | SCOPE_EXIT({ glPixelStorei(GL_PACK_ROW_LENGTH, 0); }); |
| @@ -300,60 +230,30 @@ void CachedSurface::FlushBufferImpl() { | |||
| 300 | for (u32 level = 0; level < params.GetNumLevels(); ++level) { | 230 | for (u32 level = 0; level < params.GetNumLevels(); ++level) { |
| 301 | glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level))); | 231 | glPixelStorei(GL_PACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level))); |
| 302 | if (is_compressed) { | 232 | if (is_compressed) { |
| 303 | glGetCompressedTextureImage( | 233 | glGetCompressedTextureImage(texture.handle, level, |
| 304 | texture.handle, level, static_cast<GLsizei>(params.GetHostMipmapSize(level)), | 234 | static_cast<GLsizei>(params.GetHostMipmapSize(level)), |
| 305 | staging_buffer.data() + params.GetHostMipmapLevelOffset(level)); | 235 | GetStagingBufferLevelData(level)); |
| 306 | } else { | 236 | } else { |
| 307 | glGetTextureImage(texture.handle, level, format, type, | 237 | glGetTextureImage(texture.handle, level, format, type, |
| 308 | static_cast<GLsizei>(params.GetHostMipmapSize(level)), | 238 | static_cast<GLsizei>(params.GetHostMipmapSize(level)), |
| 309 | staging_buffer.data() + params.GetHostMipmapLevelOffset(level)); | 239 | GetStagingBufferLevelData(level)); |
| 310 | } | 240 | } |
| 311 | } | 241 | } |
| 312 | |||
| 313 | if (params.IsTiled()) { | ||
| 314 | ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {}", | ||
| 315 | params.GetBlockWidth()); | ||
| 316 | for (u32 level = 0; level < params.GetNumLevels(); ++level) { | ||
| 317 | u8* const buffer = staging_buffer.data() + params.GetHostMipmapLevelOffset(level); | ||
| 318 | SwizzleFunc(MortonSwizzleMode::LinearToMorton, GetHostPtr(), params, buffer, level); | ||
| 319 | } | ||
| 320 | } else { | ||
| 321 | UNIMPLEMENTED(); | ||
| 322 | /* | ||
| 323 | ASSERT(params.GetTarget() == SurfaceTarget::Texture2D); | ||
| 324 | ASSERT(params.GetNumLevels() == 1); | ||
| 325 | |||
| 326 | const u32 bpp{params.GetFormatBpp() / 8}; | ||
| 327 | const u32 copy_size{params.GetWidth() * bpp}; | ||
| 328 | if (params.GetPitch() == copy_size) { | ||
| 329 | std::memcpy(host_ptr, staging_buffer.data(), GetSizeInBytes()); | ||
| 330 | } else { | ||
| 331 | u8* start{host_ptr}; | ||
| 332 | const u8* read_to{staging_buffer.data()}; | ||
| 333 | for (u32 h = params.GetHeight(); h > 0; --h) { | ||
| 334 | std::memcpy(start, read_to, copy_size); | ||
| 335 | start += params.GetPitch(); | ||
| 336 | read_to += copy_size; | ||
| 337 | } | ||
| 338 | } | ||
| 339 | */ | ||
| 340 | } | ||
| 341 | } | 242 | } |
| 342 | 243 | ||
| 343 | void CachedSurface::UploadTextureImpl() { | 244 | void CachedSurface::UploadTextureImpl() { |
| 245 | SCOPE_EXIT({ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); }); | ||
| 344 | for (u32 level = 0; level < params.GetNumLevels(); ++level) { | 246 | for (u32 level = 0; level < params.GetNumLevels(); ++level) { |
| 345 | UploadTextureMipmap(level); | 247 | UploadTextureMipmap(level); |
| 346 | } | 248 | } |
| 347 | } | 249 | } |
| 348 | 250 | ||
| 349 | void CachedSurface::UploadTextureMipmap(u32 level) { | 251 | void CachedSurface::UploadTextureMipmap(u32 level) { |
| 350 | u8* buffer{staging_buffer.data() + params.GetHostMipmapLevelOffset(level)}; | ||
| 351 | |||
| 352 | // TODO(Rodrigo): Optimize alignment | 252 | // TODO(Rodrigo): Optimize alignment |
| 353 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | 253 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
| 354 | glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level))); | 254 | glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.GetMipWidth(level))); |
| 355 | SCOPE_EXIT({ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); }); | ||
| 356 | 255 | ||
| 256 | u8* buffer{GetStagingBufferLevelData(level)}; | ||
| 357 | if (is_compressed) { | 257 | if (is_compressed) { |
| 358 | const auto image_size{static_cast<GLsizei>(params.GetHostMipmapSize(level))}; | 258 | const auto image_size{static_cast<GLsizei>(params.GetHostMipmapSize(level))}; |
| 359 | switch (params.GetTarget()) { | 259 | switch (params.GetTarget()) { |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index e6448c6f8..0a69be233 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -39,8 +39,6 @@ public: | |||
| 39 | explicit CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params); | 39 | explicit CachedSurface(TextureCacheOpenGL& texture_cache, const SurfaceParams& params); |
| 40 | ~CachedSurface(); | 40 | ~CachedSurface(); |
| 41 | 41 | ||
| 42 | void LoadBuffer(); | ||
| 43 | |||
| 44 | GLenum GetTarget() const { | 42 | GLenum GetTarget() const { |
| 45 | return target; | 43 | return target; |
| 46 | } | 44 | } |
| @@ -54,9 +52,8 @@ protected: | |||
| 54 | 52 | ||
| 55 | std::unique_ptr<CachedSurfaceView> CreateView(const ViewKey& view_key); | 53 | std::unique_ptr<CachedSurfaceView> CreateView(const ViewKey& view_key); |
| 56 | 54 | ||
| 57 | void FlushBufferImpl(); | ||
| 58 | |||
| 59 | void UploadTextureImpl(); | 55 | void UploadTextureImpl(); |
| 56 | void DownloadTextureImpl(); | ||
| 60 | 57 | ||
| 61 | private: | 58 | private: |
| 62 | void UploadTextureMipmap(u32 level); | 59 | void UploadTextureMipmap(u32 level); |
| @@ -68,8 +65,6 @@ private: | |||
| 68 | GLenum target{}; | 65 | GLenum target{}; |
| 69 | 66 | ||
| 70 | OGLTexture texture; | 67 | OGLTexture texture; |
| 71 | |||
| 72 | std::vector<u8> staging_buffer; | ||
| 73 | }; | 68 | }; |
| 74 | 69 | ||
| 75 | class CachedSurfaceView final { | 70 | class CachedSurfaceView final { |
diff --git a/src/video_core/texture_cache.cpp b/src/video_core/texture_cache.cpp index b78a7d951..146e8ed9b 100644 --- a/src/video_core/texture_cache.cpp +++ b/src/video_core/texture_cache.cpp | |||
| @@ -7,14 +7,16 @@ | |||
| 7 | #include "common/cityhash.h" | 7 | #include "common/cityhash.h" |
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "video_core/morton.h" | ||
| 10 | #include "video_core/surface.h" | 11 | #include "video_core/surface.h" |
| 11 | #include "video_core/texture_cache.h" | 12 | #include "video_core/texture_cache.h" |
| 13 | #include "video_core/textures/convert.h" | ||
| 12 | #include "video_core/textures/decoders.h" | 14 | #include "video_core/textures/decoders.h" |
| 13 | #include "video_core/textures/texture.h" | 15 | #include "video_core/textures/texture.h" |
| 14 | 16 | ||
| 15 | namespace VideoCommon { | 17 | namespace VideoCommon { |
| 16 | 18 | ||
| 17 | using VideoCore::Surface::SurfaceTarget; | 19 | using VideoCore::MortonSwizzleMode; |
| 18 | 20 | ||
| 19 | using VideoCore::Surface::ComponentTypeFromDepthFormat; | 21 | using VideoCore::Surface::ComponentTypeFromDepthFormat; |
| 20 | using VideoCore::Surface::ComponentTypeFromRenderTarget; | 22 | using VideoCore::Surface::ComponentTypeFromRenderTarget; |
| @@ -22,12 +24,118 @@ using VideoCore::Surface::ComponentTypeFromTexture; | |||
| 22 | using VideoCore::Surface::PixelFormatFromDepthFormat; | 24 | using VideoCore::Surface::PixelFormatFromDepthFormat; |
| 23 | using VideoCore::Surface::PixelFormatFromRenderTargetFormat; | 25 | using VideoCore::Surface::PixelFormatFromRenderTargetFormat; |
| 24 | using VideoCore::Surface::PixelFormatFromTextureFormat; | 26 | using VideoCore::Surface::PixelFormatFromTextureFormat; |
| 27 | using VideoCore::Surface::SurfaceTarget; | ||
| 25 | using VideoCore::Surface::SurfaceTargetFromTextureType; | 28 | using VideoCore::Surface::SurfaceTargetFromTextureType; |
| 26 | 29 | ||
| 30 | using Tegra::Texture::ConvertFromGuestToHost; | ||
| 31 | |||
| 32 | namespace { | ||
| 33 | |||
| 27 | constexpr u32 GetMipmapSize(bool uncompressed, u32 mip_size, u32 tile) { | 34 | constexpr u32 GetMipmapSize(bool uncompressed, u32 mip_size, u32 tile) { |
| 28 | return uncompressed ? mip_size : std::max(1U, (mip_size + tile - 1) / tile); | 35 | return uncompressed ? mip_size : std::max(1U, (mip_size + tile - 1) / tile); |
| 29 | } | 36 | } |
| 30 | 37 | ||
| 38 | void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer, | ||
| 39 | u32 level) { | ||
| 40 | const u32 width{params.GetMipWidth(level)}; | ||
| 41 | const u32 height{params.GetMipHeight(level)}; | ||
| 42 | const u32 block_height{params.GetMipBlockHeight(level)}; | ||
| 43 | const u32 block_depth{params.GetMipBlockDepth(level)}; | ||
| 44 | |||
| 45 | std::size_t guest_offset{params.GetGuestMipmapLevelOffset(level)}; | ||
| 46 | if (params.IsLayered()) { | ||
| 47 | std::size_t host_offset{0}; | ||
| 48 | const std::size_t guest_stride = params.GetGuestLayerSize(); | ||
| 49 | const std::size_t host_stride = params.GetHostLayerSize(level); | ||
| 50 | for (u32 layer = 0; layer < params.GetNumLayers(); layer++) { | ||
| 51 | MortonSwizzle(mode, params.GetPixelFormat(), width, block_height, height, block_depth, | ||
| 52 | 1, params.GetTileWidthSpacing(), buffer + host_offset, | ||
| 53 | memory + guest_offset); | ||
| 54 | guest_offset += guest_stride; | ||
| 55 | host_offset += host_stride; | ||
| 56 | } | ||
| 57 | } else { | ||
| 58 | MortonSwizzle(mode, params.GetPixelFormat(), width, block_height, height, block_depth, | ||
| 59 | params.GetMipDepth(level), params.GetTileWidthSpacing(), buffer, | ||
| 60 | memory + guest_offset); | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | } // Anonymous namespace | ||
| 65 | |||
| 66 | SurfaceBaseImpl::SurfaceBaseImpl(const SurfaceParams& params) : params{params} { | ||
| 67 | staging_buffer.resize(params.GetHostSizeInBytes()); | ||
| 68 | } | ||
| 69 | |||
| 70 | SurfaceBaseImpl::~SurfaceBaseImpl() = default; | ||
| 71 | |||
| 72 | void SurfaceBaseImpl::LoadBuffer() { | ||
| 73 | if (params.IsTiled()) { | ||
| 74 | ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {} on texture target {}", | ||
| 75 | params.GetBlockWidth(), static_cast<u32>(params.GetTarget())); | ||
| 76 | for (u32 level = 0; level < params.GetNumLevels(); ++level) { | ||
| 77 | u8* const buffer{GetStagingBufferLevelData(level)}; | ||
| 78 | SwizzleFunc(MortonSwizzleMode::MortonToLinear, host_ptr, params, buffer, level); | ||
| 79 | } | ||
| 80 | } else { | ||
| 81 | ASSERT_MSG(params.GetNumLevels() == 1, "Linear mipmap loading is not implemented"); | ||
| 82 | const u32 bpp{GetFormatBpp(params.GetPixelFormat()) / CHAR_BIT}; | ||
| 83 | const u32 block_width{params.GetDefaultBlockWidth()}; | ||
| 84 | const u32 block_height{params.GetDefaultBlockHeight()}; | ||
| 85 | const u32 width{(params.GetWidth() + block_width - 1) / block_width}; | ||
| 86 | const u32 height{(params.GetHeight() + block_height - 1) / block_height}; | ||
| 87 | const u32 copy_size{width * bpp}; | ||
| 88 | if (params.GetPitch() == copy_size) { | ||
| 89 | std::memcpy(staging_buffer.data(), host_ptr, params.GetHostSizeInBytes()); | ||
| 90 | } else { | ||
| 91 | const u8* start{host_ptr}; | ||
| 92 | u8* write_to{staging_buffer.data()}; | ||
| 93 | for (u32 h = height; h > 0; --h) { | ||
| 94 | std::memcpy(write_to, start, copy_size); | ||
| 95 | start += params.GetPitch(); | ||
| 96 | write_to += copy_size; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | for (u32 level = 0; level < params.GetNumLevels(); ++level) { | ||
| 102 | ConvertFromGuestToHost(GetStagingBufferLevelData(level), params.GetPixelFormat(), | ||
| 103 | params.GetMipWidth(level), params.GetMipHeight(level), | ||
| 104 | params.GetMipDepth(level), true, true); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | void SurfaceBaseImpl::FlushBuffer() { | ||
| 109 | if (params.IsTiled()) { | ||
| 110 | ASSERT_MSG(params.GetBlockWidth() == 1, "Block width is defined as {}", | ||
| 111 | params.GetBlockWidth()); | ||
| 112 | for (u32 level = 0; level < params.GetNumLevels(); ++level) { | ||
| 113 | u8* const buffer = GetStagingBufferLevelData(level); | ||
| 114 | SwizzleFunc(MortonSwizzleMode::LinearToMorton, GetHostPtr(), params, buffer, level); | ||
| 115 | } | ||
| 116 | } else { | ||
| 117 | UNIMPLEMENTED(); | ||
| 118 | /* | ||
| 119 | ASSERT(params.GetTarget() == SurfaceTarget::Texture2D); | ||
| 120 | ASSERT(params.GetNumLevels() == 1); | ||
| 121 | |||
| 122 | const u32 bpp{params.GetFormatBpp() / 8}; | ||
| 123 | const u32 copy_size{params.GetWidth() * bpp}; | ||
| 124 | if (params.GetPitch() == copy_size) { | ||
| 125 | std::memcpy(host_ptr, staging_buffer.data(), GetSizeInBytes()); | ||
| 126 | } else { | ||
| 127 | u8* start{host_ptr}; | ||
| 128 | const u8* read_to{staging_buffer.data()}; | ||
| 129 | for (u32 h = params.GetHeight(); h > 0; --h) { | ||
| 130 | std::memcpy(start, read_to, copy_size); | ||
| 131 | start += params.GetPitch(); | ||
| 132 | read_to += copy_size; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | */ | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 31 | SurfaceParams SurfaceParams::CreateForTexture(Core::System& system, | 139 | SurfaceParams SurfaceParams::CreateForTexture(Core::System& system, |
| 32 | const Tegra::Texture::FullTextureInfo& config) { | 140 | const Tegra::Texture::FullTextureInfo& config) { |
| 33 | SurfaceParams params; | 141 | SurfaceParams params; |
diff --git a/src/video_core/texture_cache.h b/src/video_core/texture_cache.h index f22e8e776..90c72cb15 100644 --- a/src/video_core/texture_cache.h +++ b/src/video_core/texture_cache.h | |||
| @@ -273,37 +273,11 @@ struct hash<VideoCommon::ViewKey> { | |||
| 273 | 273 | ||
| 274 | namespace VideoCommon { | 274 | namespace VideoCommon { |
| 275 | 275 | ||
| 276 | template <typename TTextureCache, typename TView, typename TExecutionContext> | 276 | class SurfaceBaseImpl { |
| 277 | class SurfaceBase { | ||
| 278 | static_assert(std::is_trivially_copyable_v<TExecutionContext>); | ||
| 279 | |||
| 280 | public: | 277 | public: |
| 281 | virtual void LoadBuffer() = 0; | 278 | void LoadBuffer(); |
| 282 | |||
| 283 | virtual TExecutionContext FlushBuffer(TExecutionContext exctx) = 0; | ||
| 284 | |||
| 285 | virtual TExecutionContext UploadTexture(TExecutionContext exctx) = 0; | ||
| 286 | |||
| 287 | TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) { | ||
| 288 | if (view_addr < gpu_addr || !params.IsFamiliar(view_params)) { | ||
| 289 | // It can't be a view if it's in a prior address. | ||
| 290 | return {}; | ||
| 291 | } | ||
| 292 | |||
| 293 | const auto relative_offset{static_cast<u64>(view_addr - gpu_addr)}; | ||
| 294 | const auto it{view_offset_map.find(relative_offset)}; | ||
| 295 | if (it == view_offset_map.end()) { | ||
| 296 | // Couldn't find an aligned view. | ||
| 297 | return {}; | ||
| 298 | } | ||
| 299 | const auto [layer, level] = it->second; | ||
| 300 | |||
| 301 | if (!params.IsViewValid(view_params, layer, level)) { | ||
| 302 | return {}; | ||
| 303 | } | ||
| 304 | 279 | ||
| 305 | return GetView(layer, view_params.GetNumLayers(), level, view_params.GetNumLevels()); | 280 | void FlushBuffer(); |
| 306 | } | ||
| 307 | 281 | ||
| 308 | GPUVAddr GetGpuAddr() const { | 282 | GPUVAddr GetGpuAddr() const { |
| 309 | ASSERT(is_registered); | 283 | ASSERT(is_registered); |
| @@ -325,27 +299,10 @@ public: | |||
| 325 | return cache_addr; | 299 | return cache_addr; |
| 326 | } | 300 | } |
| 327 | 301 | ||
| 328 | std::size_t GetSizeInBytes() const { | ||
| 329 | return params.GetGuestSizeInBytes(); | ||
| 330 | } | ||
| 331 | |||
| 332 | void MarkAsModified(bool is_modified_) { | ||
| 333 | is_modified = is_modified_; | ||
| 334 | if (is_modified_) { | ||
| 335 | modification_tick = texture_cache.Tick(); | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | const SurfaceParams& GetSurfaceParams() const { | 302 | const SurfaceParams& GetSurfaceParams() const { |
| 340 | return params; | 303 | return params; |
| 341 | } | 304 | } |
| 342 | 305 | ||
| 343 | TView* GetView(GPUVAddr view_addr, const SurfaceParams& view_params) { | ||
| 344 | TView* view{TryGetView(view_addr, view_params)}; | ||
| 345 | ASSERT(view != nullptr); | ||
| 346 | return view; | ||
| 347 | } | ||
| 348 | |||
| 349 | void Register(GPUVAddr gpu_addr_, VAddr cpu_addr_, u8* host_ptr_) { | 306 | void Register(GPUVAddr gpu_addr_, VAddr cpu_addr_, u8* host_ptr_) { |
| 350 | ASSERT(!is_registered); | 307 | ASSERT(!is_registered); |
| 351 | is_registered = true; | 308 | is_registered = true; |
| @@ -361,30 +318,95 @@ public: | |||
| 361 | is_registered = false; | 318 | is_registered = false; |
| 362 | } | 319 | } |
| 363 | 320 | ||
| 364 | u64 GetModificationTick() const { | ||
| 365 | return modification_tick; | ||
| 366 | } | ||
| 367 | |||
| 368 | bool IsRegistered() const { | 321 | bool IsRegistered() const { |
| 369 | return is_registered; | 322 | return is_registered; |
| 370 | } | 323 | } |
| 371 | 324 | ||
| 372 | protected: | 325 | std::size_t GetSizeInBytes() const { |
| 373 | explicit SurfaceBase(TTextureCache& texture_cache, const SurfaceParams& params) | 326 | return params.GetGuestSizeInBytes(); |
| 374 | : params{params}, texture_cache{texture_cache}, view_offset_map{ | 327 | } |
| 375 | params.CreateViewOffsetMap()} {} | ||
| 376 | 328 | ||
| 377 | ~SurfaceBase() = default; | 329 | u8* GetStagingBufferLevelData(u32 level) { |
| 330 | return staging_buffer.data() + params.GetHostMipmapLevelOffset(level); | ||
| 331 | } | ||
| 332 | |||
| 333 | protected: | ||
| 334 | explicit SurfaceBaseImpl(const SurfaceParams& params); | ||
| 335 | ~SurfaceBaseImpl(); // non-virtual is intended | ||
| 378 | 336 | ||
| 379 | virtual void DecorateSurfaceName() = 0; | 337 | virtual void DecorateSurfaceName() = 0; |
| 380 | 338 | ||
| 381 | virtual std::unique_ptr<TView> CreateView(const ViewKey& view_key) = 0; | 339 | const SurfaceParams params; |
| 340 | |||
| 341 | private: | ||
| 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 | |||
| 351 | template <typename TTextureCache, typename TView, typename TExecutionContext> | ||
| 352 | class SurfaceBase : public SurfaceBaseImpl { | ||
| 353 | static_assert(std::is_trivially_copyable_v<TExecutionContext>); | ||
| 354 | |||
| 355 | public: | ||
| 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 | } | ||
| 382 | 393 | ||
| 383 | bool IsModified() const { | 394 | bool IsModified() const { |
| 384 | return is_modified; | 395 | return is_modified; |
| 385 | } | 396 | } |
| 386 | 397 | ||
| 387 | const SurfaceParams params; | 398 | u64 GetModificationTick() const { |
| 399 | return modification_tick; | ||
| 400 | } | ||
| 401 | |||
| 402 | protected: | ||
| 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; | ||
| 388 | 410 | ||
| 389 | private: | 411 | private: |
| 390 | TView* GetView(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels) { | 412 | TView* GetView(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels) { |
| @@ -400,13 +422,8 @@ private: | |||
| 400 | TTextureCache& texture_cache; | 422 | TTextureCache& texture_cache; |
| 401 | const std::map<u64, std::pair<u32, u32>> view_offset_map; | 423 | const std::map<u64, std::pair<u32, u32>> view_offset_map; |
| 402 | 424 | ||
| 403 | GPUVAddr gpu_addr{}; | ||
| 404 | VAddr cpu_addr{}; | ||
| 405 | u8* host_ptr{}; | ||
| 406 | CacheAddr cache_addr{}; | ||
| 407 | u64 modification_tick{}; | ||
| 408 | bool is_modified{}; | 425 | bool is_modified{}; |
| 409 | bool is_registered{}; | 426 | u64 modification_tick{}; |
| 410 | std::unordered_map<ViewKey, std::unique_ptr<TView>> views; | 427 | std::unordered_map<ViewKey, std::unique_ptr<TView>> views; |
| 411 | }; | 428 | }; |
| 412 | 429 | ||
| @@ -560,7 +577,7 @@ private: | |||
| 560 | if (!fast_view) { | 577 | if (!fast_view) { |
| 561 | // Flush even when we don't care about the contents, to preserve memory not | 578 | // Flush even when we don't care about the contents, to preserve memory not |
| 562 | // written by the new surface. | 579 | // written by the new surface. |
| 563 | exctx = surface->FlushBuffer(exctx); | 580 | exctx = FlushSurface(exctx, surface); |
| 564 | } | 581 | } |
| 565 | Unregister(surface); | 582 | Unregister(surface); |
| 566 | } | 583 | } |
| @@ -590,6 +607,16 @@ private: | |||
| 590 | return exctx; | 607 | return exctx; |
| 591 | } | 608 | } |
| 592 | 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 | |||
| 593 | std::vector<std::shared_ptr<TSurface>> GetSurfacesInRegion(CacheAddr cache_addr, | 620 | std::vector<std::shared_ptr<TSurface>> GetSurfacesInRegion(CacheAddr cache_addr, |
| 594 | std::size_t size) const { | 621 | std::size_t size) const { |
| 595 | if (size == 0) { | 622 | if (size == 0) { |
| @@ -701,8 +728,8 @@ private: | |||
| 701 | template <typename TTextureCache, typename TView> | 728 | template <typename TTextureCache, typename TView> |
| 702 | class SurfaceBaseContextless : public SurfaceBase<TTextureCache, TView, DummyExecutionContext> { | 729 | class SurfaceBaseContextless : public SurfaceBase<TTextureCache, TView, DummyExecutionContext> { |
| 703 | public: | 730 | public: |
| 704 | DummyExecutionContext FlushBuffer(DummyExecutionContext) { | 731 | DummyExecutionContext DownloadTexture(DummyExecutionContext) { |
| 705 | FlushBufferImpl(); | 732 | DownloadTextureImpl(); |
| 706 | return {}; | 733 | return {}; |
| 707 | } | 734 | } |
| 708 | 735 | ||
| @@ -715,7 +742,7 @@ protected: | |||
| 715 | explicit SurfaceBaseContextless(TTextureCache& texture_cache, const SurfaceParams& params) | 742 | explicit SurfaceBaseContextless(TTextureCache& texture_cache, const SurfaceParams& params) |
| 716 | : SurfaceBase<TTextureCache, TView, DummyExecutionContext>{texture_cache, params} {} | 743 | : SurfaceBase<TTextureCache, TView, DummyExecutionContext>{texture_cache, params} {} |
| 717 | 744 | ||
| 718 | virtual void FlushBufferImpl() = 0; | 745 | virtual void DownloadTextureImpl() = 0; |
| 719 | 746 | ||
| 720 | virtual void UploadTextureImpl() = 0; | 747 | virtual void UploadTextureImpl() = 0; |
| 721 | }; | 748 | }; |