diff options
| author | 2019-04-24 02:45:03 -0300 | |
|---|---|---|
| committer | 2019-06-20 21:36:11 -0300 | |
| commit | 5f3aacdc3760f0e9e0daeda3ee4c55e42fc9397e (patch) | |
| tree | 6c95776e1de8c347544745df1784424cafaeb414 /src/video_core/texture_cache.h | |
| 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/video_core/texture_cache.h')
| -rw-r--r-- | src/video_core/texture_cache.h | 161 |
1 files changed, 94 insertions, 67 deletions
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 | }; |