From 1b4503c571d3b961efe74fa7e35d5fa14941ec09 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 24 Apr 2019 16:35:54 -0300 Subject: texture_cache: Split texture cache into different files --- src/video_core/texture_cache/surface_base.h | 172 ++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 src/video_core/texture_cache/surface_base.h (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h new file mode 100644 index 000000000..d0142a9e6 --- /dev/null +++ b/src/video_core/texture_cache/surface_base.h @@ -0,0 +1,172 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "common/assert.h" +#include "common/common_types.h" +#include "video_core/gpu.h" +#include "video_core/texture_cache/surface_params.h" +#include "video_core/texture_cache/surface_view.h" + +namespace VideoCommon { + +class SurfaceBaseImpl { +public: + void LoadBuffer(); + + void FlushBuffer(); + + GPUVAddr GetGpuAddr() const { + ASSERT(is_registered); + return gpu_addr; + } + + VAddr GetCpuAddr() const { + ASSERT(is_registered); + return cpu_addr; + } + + u8* GetHostPtr() const { + ASSERT(is_registered); + return host_ptr; + } + + CacheAddr GetCacheAddr() const { + ASSERT(is_registered); + return cache_addr; + } + + const SurfaceParams& GetSurfaceParams() const { + return params; + } + + void Register(GPUVAddr gpu_addr_, VAddr cpu_addr_, u8* host_ptr_) { + ASSERT(!is_registered); + is_registered = true; + gpu_addr = gpu_addr_; + cpu_addr = cpu_addr_; + host_ptr = host_ptr_; + cache_addr = ToCacheAddr(host_ptr_); + DecorateSurfaceName(); + } + + void Unregister() { + ASSERT(is_registered); + is_registered = false; + } + + bool IsRegistered() const { + return is_registered; + } + + std::size_t GetSizeInBytes() const { + return params.GetGuestSizeInBytes(); + } + + u8* GetStagingBufferLevelData(u32 level) { + return staging_buffer.data() + params.GetHostMipmapLevelOffset(level); + } + +protected: + explicit SurfaceBaseImpl(const SurfaceParams& params); + ~SurfaceBaseImpl(); // non-virtual is intended + + virtual void DecorateSurfaceName() = 0; + + const SurfaceParams params; + +private: + GPUVAddr gpu_addr{}; + VAddr cpu_addr{}; + u8* host_ptr{}; + CacheAddr cache_addr{}; + bool is_registered{}; + + std::vector staging_buffer; +}; + +template +class SurfaceBase : public SurfaceBaseImpl { + static_assert(std::is_trivially_copyable_v); + +public: + virtual TExecutionContext UploadTexture(TExecutionContext exctx) = 0; + + virtual TExecutionContext DownloadTexture(TExecutionContext exctx) = 0; + + TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) { + if (view_addr < GetGpuAddr() || !params.IsFamiliar(view_params)) { + // It can't be a view if it's in a prior address. + return {}; + } + + const auto relative_offset{static_cast(view_addr - GetGpuAddr())}; + const auto it{view_offset_map.find(relative_offset)}; + if (it == view_offset_map.end()) { + // Couldn't find an aligned view. + return {}; + } + const auto [layer, level] = it->second; + + if (!params.IsViewValid(view_params, layer, level)) { + return {}; + } + + return GetView(layer, view_params.GetNumLayers(), level, view_params.GetNumLevels()); + } + + void MarkAsModified(bool is_modified_) { + is_modified = is_modified_; + if (is_modified_) { + modification_tick = texture_cache.Tick(); + } + } + + TView* GetView(GPUVAddr view_addr, const SurfaceParams& view_params) { + TView* view{TryGetView(view_addr, view_params)}; + ASSERT(view != nullptr); + return view; + } + + bool IsModified() const { + return is_modified; + } + + u64 GetModificationTick() const { + return modification_tick; + } + +protected: + explicit SurfaceBase(TTextureCache& texture_cache, const SurfaceParams& params) + : SurfaceBaseImpl{params}, texture_cache{texture_cache}, + view_offset_map{params.CreateViewOffsetMap()} {} + + ~SurfaceBase() = default; + + virtual std::unique_ptr CreateView(const ViewKey& view_key) = 0; + +private: + TView* GetView(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels) { + const ViewKey key{base_layer, num_layers, base_level, num_levels}; + const auto [entry, is_cache_miss] = views.try_emplace(key); + auto& view{entry->second}; + if (is_cache_miss) { + view = CreateView(key); + } + return view.get(); + } + + TTextureCache& texture_cache; + const std::map> view_offset_map; + + std::unordered_map> views; + + bool is_modified{}; + u64 modification_tick{}; +}; + +} // namespace VideoCommon -- cgit v1.2.3 From 6c410104f4f6953ac37095aa5e65804bf115c026 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 25 Apr 2019 13:41:57 -0300 Subject: texture_cache: Remove execution context copies from the texture cache This is done to simplify the OpenGL implementation, it is needed for Vulkan. --- src/video_core/texture_cache/surface_base.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index d0142a9e6..eed8dc59d 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -89,14 +89,12 @@ private: std::vector staging_buffer; }; -template +template class SurfaceBase : public SurfaceBaseImpl { - static_assert(std::is_trivially_copyable_v); - public: - virtual TExecutionContext UploadTexture(TExecutionContext exctx) = 0; + virtual void UploadTexture() = 0; - virtual TExecutionContext DownloadTexture(TExecutionContext exctx) = 0; + virtual void DownloadTexture() = 0; TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) { if (view_addr < GetGpuAddr() || !params.IsFamiliar(view_params)) { -- cgit v1.2.3 From 3d471e732d688c20aef73a506bdb6126002d3193 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 7 May 2019 10:56:45 -0400 Subject: Correct Surface Base and Views for new Texture Cache --- src/video_core/texture_cache/surface_base.h | 297 ++++++++++++++++++++-------- 1 file changed, 220 insertions(+), 77 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') 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 @@ #pragma once +#include #include +#include #include "common/assert.h" #include "common/common_types.h" #include "video_core/gpu.h" +#include "video_core/morton.h" +#include "video_core/texture_cache/copy_params.h" #include "video_core/texture_cache/surface_params.h" #include "video_core/texture_cache/surface_view.h" +template> +ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp={}) +{ + // Note: BOTH type T and the type after ForwardIt is dereferenced + // must be implicitly convertible to BOTH Type1 and Type2, used in Compare. + // This is stricter than lower_bound requirement (see above) + + first = std::lower_bound(first, last, value, comp); + return first != last && !comp(value, *first) ? first : last; +} + +namespace Tegra { +class MemoryManager; +} + namespace VideoCommon { +using VideoCore::Surface::SurfaceTarget; +using VideoCore::MortonSwizzleMode; + class SurfaceBaseImpl { public: - void LoadBuffer(); + void LoadBuffer(Tegra::MemoryManager& memory_manager, std::vector& staging_buffer); - void FlushBuffer(); + void FlushBuffer(std::vector& staging_buffer); GPUVAddr GetGpuAddr() const { - ASSERT(is_registered); return gpu_addr; } + GPUVAddr GetGpuAddrEnd() const { + return gpu_addr_end; + } + + bool Overlaps(const GPUVAddr start, const GPUVAddr end) const { + return (gpu_addr < end) && (gpu_addr_end > start); + } + + // Use only when recycling a surface + void SetGpuAddr(const GPUVAddr new_addr) { + gpu_addr = new_addr; + gpu_addr_end = new_addr + memory_size; + } + VAddr GetCpuAddr() const { - ASSERT(is_registered); - return cpu_addr; + return gpu_addr; + } + + void SetCpuAddr(const VAddr new_addr) { + cpu_addr = new_addr; } u8* GetHostPtr() const { - ASSERT(is_registered); return host_ptr; } - CacheAddr GetCacheAddr() const { - ASSERT(is_registered); - return cache_addr; + void SetHostPtr(u8* new_addr) { + host_ptr = new_addr; } const SurfaceParams& GetSurfaceParams() const { return params; } - void Register(GPUVAddr gpu_addr_, VAddr cpu_addr_, u8* host_ptr_) { - ASSERT(!is_registered); - is_registered = true; - gpu_addr = gpu_addr_; - cpu_addr = cpu_addr_; - host_ptr = host_ptr_; - cache_addr = ToCacheAddr(host_ptr_); - DecorateSurfaceName(); + std::size_t GetSizeInBytes() const { + return memory_size; } - void Unregister() { - ASSERT(is_registered); - is_registered = false; + std::size_t GetHostSizeInBytes() const { + return host_memory_size; } - bool IsRegistered() const { - return is_registered; + std::size_t GetMipmapSize(const u32 level) const { + return mipmap_sizes[level]; } - std::size_t GetSizeInBytes() const { - return params.GetGuestSizeInBytes(); + bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const { + return params.pixel_format == pixel_format; + } + + bool MatchTarget(VideoCore::Surface::SurfaceTarget target) const { + return params.target == target; + } + + bool MatchesTopology(const SurfaceParams& rhs) const { + const u32 src_bpp = params.GetBytesPerPixel(); + const u32 dst_bpp = rhs.GetBytesPerPixel(); + return std::tie(src_bpp, params.is_tiled) == std::tie(dst_bpp, rhs.is_tiled); + } + + bool MatchesStructure(const SurfaceParams& rhs) const { + if (params.is_tiled) { + const u32 a_width1 = params.GetBlockAlignedWidth(); + const u32 a_width2 = rhs.GetBlockAlignedWidth(); + return std::tie(a_width1, params.height, params.depth, params.block_width, + params.block_height, params.block_depth, params.tile_width_spacing) == + std::tie(a_width2, rhs.height, rhs.depth, rhs.block_width, rhs.block_height, + rhs.block_depth, rhs.tile_width_spacing); + } else { + return std::tie(params.width, params.height, params.pitch) == + std::tie(rhs.width, rhs.height, rhs.pitch); + } + } + + std::optional> GetLayerMipmap(const GPUVAddr candidate_gpu_addr) const { + if (candidate_gpu_addr < gpu_addr) + return {}; + const GPUVAddr relative_address = candidate_gpu_addr - gpu_addr; + const u32 layer = relative_address / layer_size; + const GPUVAddr mipmap_address = relative_address - layer_size * layer; + const auto mipmap_it = binary_find(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); + if (mipmap_it != mipmap_offsets.end()) { + return {{layer, std::distance(mipmap_offsets.begin(), mipmap_it)}}; + } + return {}; } - u8* GetStagingBufferLevelData(u32 level) { - return staging_buffer.data() + params.GetHostMipmapLevelOffset(level); + std::vector BreakDown() const { + auto set_up_copy = [](CopyParams& cp, const SurfaceParams& params, const u32 depth, + const u32 level) { + cp.source_x = 0; + cp.source_y = 0; + cp.source_z = 0; + cp.dest_x = 0; + cp.dest_y = 0; + cp.dest_z = 0; + cp.source_level = level; + cp.dest_level = level; + cp.width = params.GetMipWidth(level); + cp.height = params.GetMipHeight(level); + cp.depth = depth; + }; + const u32 layers = params.depth; + const u32 mipmaps = params.num_levels; + if (params.is_layered) { + std::vector result{layers * mipmaps}; + for (std::size_t layer = 0; layer < layers; layer++) { + const u32 layer_offset = layer * mipmaps; + for (std::size_t level = 0; level < mipmaps; level++) { + CopyParams& cp = result[layer_offset + level]; + set_up_copy(cp, params, layer, level); + } + } + return result; + } else { + std::vector result{mipmaps}; + for (std::size_t level = 0; level < mipmaps; level++) { + CopyParams& cp = result[level]; + set_up_copy(cp, params, params.GetMipDepth(level), level); + } + return result; + } } protected: - explicit SurfaceBaseImpl(const SurfaceParams& params); - ~SurfaceBaseImpl(); // non-virtual is intended + explicit SurfaceBaseImpl(const GPUVAddr gpu_vaddr, const SurfaceParams& params); + ~SurfaceBaseImpl() = default; virtual void DecorateSurfaceName() = 0; const SurfaceParams params; - -private: GPUVAddr gpu_addr{}; - VAddr cpu_addr{}; - u8* host_ptr{}; - CacheAddr cache_addr{}; - bool is_registered{}; + GPUVAddr gpu_addr_end{}; + std::vector mipmap_sizes; + std::vector mipmap_offsets; + const std::size_t layer_size; + const std::size_t memory_size; + const std::size_t host_memory_size; + u8* host_ptr; + VAddr cpu_addr; - std::vector staging_buffer; +private: + void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer, + u32 level); }; -template +template class SurfaceBase : public SurfaceBaseImpl { public: - virtual void UploadTexture() = 0; + virtual void UploadTexture(std::vector& staging_buffer) = 0; - virtual void DownloadTexture() = 0; + virtual void DownloadTexture(std::vector& staging_buffer) = 0; - TView* TryGetView(GPUVAddr view_addr, const SurfaceParams& view_params) { - if (view_addr < GetGpuAddr() || !params.IsFamiliar(view_params)) { - // It can't be a view if it's in a prior address. - return {}; - } + void MarkAsModified(const bool is_modified_, const u64 tick) { + is_modified = is_modified_ || is_protected; + modification_tick = tick; + } - const auto relative_offset{static_cast(view_addr - GetGpuAddr())}; - const auto it{view_offset_map.find(relative_offset)}; - if (it == view_offset_map.end()) { - // Couldn't find an aligned view. - return {}; - } - const auto [layer, level] = it->second; + void MarkAsProtected(const bool is_protected) { + this->is_protected = is_protected; + } - if (!params.IsViewValid(view_params, layer, level)) { - return {}; - } + void MarkAsPicked(const bool is_picked) { + this->is_picked = is_picked; + } - return GetView(layer, view_params.GetNumLayers(), level, view_params.GetNumLevels()); + bool IsModified() const { + return is_modified; } - void MarkAsModified(bool is_modified_) { - is_modified = is_modified_; - if (is_modified_) { - modification_tick = texture_cache.Tick(); - } + bool IsProtected() const { + return is_protected; } - TView* GetView(GPUVAddr view_addr, const SurfaceParams& view_params) { - TView* view{TryGetView(view_addr, view_params)}; - ASSERT(view != nullptr); - return view; + bool IsRegistered() const { + return is_registered; } - bool IsModified() const { - return is_modified; + bool IsPicked() const { + return is_picked; + } + + void MarkAsRegistered(bool is_reg) { + is_registered = is_reg; } u64 GetModificationTick() const { return modification_tick; } + TView EmplaceOverview(const SurfaceParams& overview_params) { + ViewParams vp{}; + vp.base_level = 0; + vp.num_levels = params.num_levels; + vp.target = overview_params.target; + if (params.is_layered && !overview_params.is_layered) { + vp.base_layer = 0; + vp.num_layers = 1; + } else { + vp.base_layer = 0; + vp.num_layers = params.depth; + } + return GetView(vp); + } + + std::optional EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { + if (view_addr < gpu_addr) + return {}; + if (params.target == SurfaceTarget::Texture3D || view_params.target == SurfaceTarget::Texture3D) { + return {}; + } + const std::size_t size = view_params.GetGuestSizeInBytes(); + const GPUVAddr relative_address = view_addr - gpu_addr; + auto layer_mipmap = GetLayerMipmap(relative_address); + if (!layer_mipmap) { + return {}; + } + const u32 layer = (*layer_mipmap).first; + const u32 mipmap = (*layer_mipmap).second; + if (GetMipmapSize(mipmap) != size) { + // TODO: the view may cover many mimaps, this case can still go on + return {}; + } + ViewParams vp{}; + vp.base_layer = layer; + vp.num_layers = 1; + vp.base_level = mipmap; + vp.num_levels = 1; + vp.target = params.target; + return {GetView(vp)}; + } + + TView GetMainView() const { + return main_view; + } + protected: - explicit SurfaceBase(TTextureCache& texture_cache, const SurfaceParams& params) - : SurfaceBaseImpl{params}, texture_cache{texture_cache}, - view_offset_map{params.CreateViewOffsetMap()} {} + explicit SurfaceBase(const GPUVAddr gpu_addr, const SurfaceParams& params) + : SurfaceBaseImpl(gpu_addr, params) {} ~SurfaceBase() = default; - virtual std::unique_ptr CreateView(const ViewKey& view_key) = 0; + virtual TView CreateView(const ViewParams& view_key) = 0; + + std::unordered_map views; + TView main_view; private: - TView* GetView(u32 base_layer, u32 num_layers, u32 base_level, u32 num_levels) { - const ViewKey key{base_layer, num_layers, base_level, num_levels}; + TView GetView(const ViewParams& key) { const auto [entry, is_cache_miss] = views.try_emplace(key); auto& view{entry->second}; if (is_cache_miss) { view = CreateView(key); } - return view.get(); + return view; } - TTextureCache& texture_cache; - const std::map> view_offset_map; - - std::unordered_map> views; - bool is_modified{}; + bool is_protected{}; + bool is_registered{}; + bool is_picked{}; u64 modification_tick{}; }; -- cgit v1.2.3 From b711cdce782ee604edc3c52628eb76e6b9a08b72 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 7 May 2019 13:58:37 -0400 Subject: Corrections to Structural Matching The texture will now be reconstructed if the width only matches on GoB alignment. --- src/video_core/texture_cache/surface_base.h | 66 ++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 21 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 5fd7add0a..9c048eb88 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -16,9 +16,8 @@ #include "video_core/texture_cache/surface_params.h" #include "video_core/texture_cache/surface_view.h" -template> -ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp={}) -{ +template > +ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp = {}) { // Note: BOTH type T and the type after ForwardIt is dereferenced // must be implicitly convertible to BOTH Type1 and Type2, used in Compare. // This is stricter than lower_bound requirement (see above) @@ -33,8 +32,14 @@ class MemoryManager; namespace VideoCommon { -using VideoCore::Surface::SurfaceTarget; using VideoCore::MortonSwizzleMode; +using VideoCore::Surface::SurfaceTarget; + +enum class MatchStructureResult : u32 { + FullMatch = 0, + SemiMatch = 1, + None = 2, +}; class SurfaceBaseImpl { public: @@ -106,17 +111,26 @@ public: return std::tie(src_bpp, params.is_tiled) == std::tie(dst_bpp, rhs.is_tiled); } - bool MatchesStructure(const SurfaceParams& rhs) const { + MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const { if (params.is_tiled) { - const u32 a_width1 = params.GetBlockAlignedWidth(); - const u32 a_width2 = rhs.GetBlockAlignedWidth(); - return std::tie(a_width1, params.height, params.depth, params.block_width, - params.block_height, params.block_depth, params.tile_width_spacing) == - std::tie(a_width2, rhs.height, rhs.depth, rhs.block_width, rhs.block_height, - rhs.block_depth, rhs.tile_width_spacing); + if (std::tie(params.height, params.depth, params.block_width, params.block_height, + params.block_depth, params.tile_width_spacing) == + std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, + rhs.tile_width_spacing)) { + if (params.width == rhs.width) { + return MatchStructureResult::FullMatch; + } + if (params.GetBlockAlignedWidth() == rhs.GetBlockAlignedWidth()) { + return MatchStructureResult::SemiMatch; + } + } + return MatchStructureResult::None; } else { - return std::tie(params.width, params.height, params.pitch) == - std::tie(rhs.width, rhs.height, rhs.pitch); + if (std::tie(params.width, params.height, params.pitch) == + std::tie(rhs.width, rhs.height, rhs.pitch)) { + return MatchStructureResult::FullMatch; + } + return MatchStructureResult::None; } } @@ -126,15 +140,16 @@ public: const GPUVAddr relative_address = candidate_gpu_addr - gpu_addr; const u32 layer = relative_address / layer_size; const GPUVAddr mipmap_address = relative_address - layer_size * layer; - const auto mipmap_it = binary_find(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); + const auto mipmap_it = + binary_find(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); if (mipmap_it != mipmap_offsets.end()) { return {{layer, std::distance(mipmap_offsets.begin(), mipmap_it)}}; } return {}; } - std::vector BreakDown() const { - auto set_up_copy = [](CopyParams& cp, const SurfaceParams& params, const u32 depth, + std::vector BreakDown(const SurfaceParams& in_params) const { + auto set_up_copy = [](CopyParams& cp, const u32 width, const u32 height, const u32 depth, const u32 level) { cp.source_x = 0; cp.source_y = 0; @@ -144,8 +159,8 @@ public: cp.dest_z = 0; cp.source_level = level; cp.dest_level = level; - cp.width = params.GetMipWidth(level); - cp.height = params.GetMipHeight(level); + cp.width = width; + cp.height = height; cp.depth = depth; }; const u32 layers = params.depth; @@ -156,7 +171,11 @@ public: const u32 layer_offset = layer * mipmaps; for (std::size_t level = 0; level < mipmaps; level++) { CopyParams& cp = result[layer_offset + level]; - set_up_copy(cp, params, layer, level); + const u32 width = + std::min(params.GetMipWidth(level), in_params.GetMipWidth(level)); + const u32 height = + std::min(params.GetMipHeight(level), in_params.GetMipHeight(level)); + set_up_copy(cp, width, height, layer, level); } } return result; @@ -164,7 +183,11 @@ public: std::vector result{mipmaps}; for (std::size_t level = 0; level < mipmaps; level++) { CopyParams& cp = result[level]; - set_up_copy(cp, params, params.GetMipDepth(level), level); + const u32 width = std::min(params.GetMipWidth(level), in_params.GetMipWidth(level)); + const u32 height = + std::min(params.GetMipHeight(level), in_params.GetMipHeight(level)); + const u32 depth = std::min(params.GetMipDepth(level), in_params.GetMipDepth(level)); + set_up_copy(cp, width, height, depth, level); } return result; } @@ -254,7 +277,8 @@ public: std::optional EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { if (view_addr < gpu_addr) return {}; - if (params.target == SurfaceTarget::Texture3D || view_params.target == SurfaceTarget::Texture3D) { + if (params.target == SurfaceTarget::Texture3D || + view_params.target == SurfaceTarget::Texture3D) { return {}; } const std::size_t size = view_params.GetGuestSizeInBytes(); -- cgit v1.2.3 From d86f9cd70910d4b96ec301e7d532b11d18a290a4 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 7 May 2019 17:30:36 -0400 Subject: Change texture_cache chaching from GPUAddr to CacheAddr This also reverses the changes to make invalidation and flushing through the GPU address. --- src/video_core/texture_cache/surface_base.h | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 9c048eb88..74be3237d 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -45,40 +45,40 @@ class SurfaceBaseImpl { public: void LoadBuffer(Tegra::MemoryManager& memory_manager, std::vector& staging_buffer); - void FlushBuffer(std::vector& staging_buffer); + void FlushBuffer(Tegra::MemoryManager& memory_manager, std::vector& staging_buffer); GPUVAddr GetGpuAddr() const { return gpu_addr; } - GPUVAddr GetGpuAddrEnd() const { - return gpu_addr_end; - } - - bool Overlaps(const GPUVAddr start, const GPUVAddr end) const { - return (gpu_addr < end) && (gpu_addr_end > start); + bool Overlaps(const CacheAddr start, const CacheAddr end) const { + return (cache_addr < end) && (cache_addr_end > start); } // Use only when recycling a surface void SetGpuAddr(const GPUVAddr new_addr) { gpu_addr = new_addr; - gpu_addr_end = new_addr + memory_size; } VAddr GetCpuAddr() const { - return gpu_addr; + return cpu_addr; } void SetCpuAddr(const VAddr new_addr) { cpu_addr = new_addr; } - u8* GetHostPtr() const { - return host_ptr; + CacheAddr GetCacheAddr() const { + return cache_addr; + } + + CacheAddr GetCacheAddrEnd() const { + return cache_addr_end; } - void SetHostPtr(u8* new_addr) { - host_ptr = new_addr; + void SetCacheAddr(const CacheAddr new_addr) { + cache_addr = new_addr; + cache_addr_end = new_addr + memory_size; } const SurfaceParams& GetSurfaceParams() const { @@ -201,13 +201,13 @@ protected: const SurfaceParams params; GPUVAddr gpu_addr{}; - GPUVAddr gpu_addr_end{}; std::vector mipmap_sizes; std::vector mipmap_offsets; const std::size_t layer_size; const std::size_t memory_size; const std::size_t host_memory_size; - u8* host_ptr; + CacheAddr cache_addr; + CacheAddr cache_addr_end{}; VAddr cpu_addr; private: -- cgit v1.2.3 From 1af4414861fda5cad2549372e65ecda090caf2f8 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 7 May 2019 19:09:34 -0400 Subject: Correct Mipmaps View method in Texture Cache --- src/video_core/texture_cache/surface_base.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 74be3237d..486585c9c 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -282,8 +282,7 @@ public: return {}; } const std::size_t size = view_params.GetGuestSizeInBytes(); - const GPUVAddr relative_address = view_addr - gpu_addr; - auto layer_mipmap = GetLayerMipmap(relative_address); + auto layer_mipmap = GetLayerMipmap(view_addr); if (!layer_mipmap) { return {}; } @@ -298,7 +297,7 @@ public: vp.num_layers = 1; vp.base_level = mipmap; vp.num_levels = 1; - vp.target = params.target; + vp.target = view_params.target; return {GetView(vp)}; } -- cgit v1.2.3 From 03d10ea3b420c923c14a11c86b47e2f00bc30e00 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 7 May 2019 21:28:31 -0300 Subject: copy_params: Use constructor instead of C-like initialization --- src/video_core/texture_cache/surface_base.h | 53 +++++++++++------------------ 1 file changed, 20 insertions(+), 33 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 486585c9c..029cfb055 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -149,45 +149,32 @@ public: } std::vector BreakDown(const SurfaceParams& in_params) const { - auto set_up_copy = [](CopyParams& cp, const u32 width, const u32 height, const u32 depth, - const u32 level) { - cp.source_x = 0; - cp.source_y = 0; - cp.source_z = 0; - cp.dest_x = 0; - cp.dest_y = 0; - cp.dest_z = 0; - cp.source_level = level; - cp.dest_level = level; - cp.width = width; - cp.height = height; - cp.depth = depth; - }; - const u32 layers = params.depth; - const u32 mipmaps = params.num_levels; + std::vector result; + const u32 layers{params.depth}; + const u32 mipmaps{params.num_levels}; + if (params.is_layered) { - std::vector result{layers * mipmaps}; - for (std::size_t layer = 0; layer < layers; layer++) { - const u32 layer_offset = layer * mipmaps; - for (std::size_t level = 0; level < mipmaps; level++) { - CopyParams& cp = result[layer_offset + level]; - const u32 width = - std::min(params.GetMipWidth(level), in_params.GetMipWidth(level)); - const u32 height = - std::min(params.GetMipHeight(level), in_params.GetMipHeight(level)); - set_up_copy(cp, width, height, layer, level); + result.reserve(static_cast(layers) * static_cast(mipmaps)); + for (u32 layer = 0; layer < layers; layer++) { + const u32 layer_offset{layer * mipmaps}; + for (u32 level = 0; level < mipmaps; level++) { + const u32 width{ + std::min(params.GetMipWidth(level), in_params.GetMipWidth(level))}; + const u32 height{ + std::min(params.GetMipHeight(level), in_params.GetMipHeight(level))}; + result.emplace_back(width, height, layer, level); } } return result; + } else { - std::vector result{mipmaps}; + result.reserve(mipmaps); for (std::size_t level = 0; level < mipmaps; level++) { - CopyParams& cp = result[level]; - const u32 width = std::min(params.GetMipWidth(level), in_params.GetMipWidth(level)); - const u32 height = - std::min(params.GetMipHeight(level), in_params.GetMipHeight(level)); - const u32 depth = std::min(params.GetMipDepth(level), in_params.GetMipDepth(level)); - set_up_copy(cp, width, height, depth, level); + const u32 width{std::min(params.GetMipWidth(level), in_params.GetMipWidth(level))}; + const u32 height{ + std::min(params.GetMipHeight(level), in_params.GetMipHeight(level))}; + const u32 depth{std::min(params.GetMipDepth(level), in_params.GetMipDepth(level))}; + result.emplace_back(width, height, depth, level); } return result; } -- cgit v1.2.3 From 2b30000a1ed1972e0701a8525182104b4544caa4 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 7 May 2019 21:48:02 -0300 Subject: surface_base: Silence truncation warnings and minor renames and reordering --- src/video_core/texture_cache/surface_base.h | 35 ++++++++++++++++------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 029cfb055..7cc122158 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -78,7 +78,7 @@ public: void SetCacheAddr(const CacheAddr new_addr) { cache_addr = new_addr; - cache_addr_end = new_addr + memory_size; + cache_addr_end = new_addr + guest_memory_size; } const SurfaceParams& GetSurfaceParams() const { @@ -86,7 +86,7 @@ public: } std::size_t GetSizeInBytes() const { - return memory_size; + return guest_memory_size; } std::size_t GetHostSizeInBytes() const { @@ -135,17 +135,19 @@ public: } std::optional> GetLayerMipmap(const GPUVAddr candidate_gpu_addr) const { - if (candidate_gpu_addr < gpu_addr) + if (candidate_gpu_addr < gpu_addr) { return {}; - const GPUVAddr relative_address = candidate_gpu_addr - gpu_addr; - const u32 layer = relative_address / layer_size; + } + const auto relative_address{static_cast(candidate_gpu_addr - gpu_addr)}; + const auto layer{static_cast(relative_address / layer_size)}; const GPUVAddr mipmap_address = relative_address - layer_size * layer; const auto mipmap_it = binary_find(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); - if (mipmap_it != mipmap_offsets.end()) { - return {{layer, std::distance(mipmap_offsets.begin(), mipmap_it)}}; + if (mipmap_it == mipmap_offsets.end()) { + return {}; } - return {}; + const auto level{static_cast(std::distance(mipmap_offsets.begin(), mipmap_it))}; + return std::make_pair(layer, level); } std::vector BreakDown(const SurfaceParams& in_params) const { @@ -169,7 +171,7 @@ public: } else { result.reserve(mipmaps); - for (std::size_t level = 0; level < mipmaps; level++) { + for (u32 level = 0; level < mipmaps; level++) { const u32 width{std::min(params.GetMipWidth(level), in_params.GetMipWidth(level))}; const u32 height{ std::min(params.GetMipHeight(level), in_params.GetMipHeight(level))}; @@ -181,21 +183,22 @@ public: } protected: - explicit SurfaceBaseImpl(const GPUVAddr gpu_vaddr, const SurfaceParams& params); + explicit SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params); ~SurfaceBaseImpl() = default; virtual void DecorateSurfaceName() = 0; const SurfaceParams params; - GPUVAddr gpu_addr{}; - std::vector mipmap_sizes; - std::vector mipmap_offsets; const std::size_t layer_size; - const std::size_t memory_size; + const std::size_t guest_memory_size; const std::size_t host_memory_size; - CacheAddr cache_addr; + GPUVAddr gpu_addr{}; + CacheAddr cache_addr{}; CacheAddr cache_addr_end{}; - VAddr cpu_addr; + VAddr cpu_addr{}; + + std::vector mipmap_sizes; + std::vector mipmap_offsets; private: void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer, -- cgit v1.2.3 From 16e8625a301b1f43ecebe459a40bf33f89322032 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 7 May 2019 21:55:55 -0300 Subject: surface_base: Split BreakDown into layered and non-layered variants --- src/video_core/texture_cache/surface_base.h | 93 +++++++++++++++-------------- 1 file changed, 48 insertions(+), 45 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 7cc122158..0cfb835d9 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -106,32 +106,32 @@ public: } bool MatchesTopology(const SurfaceParams& rhs) const { - const u32 src_bpp = params.GetBytesPerPixel(); - const u32 dst_bpp = rhs.GetBytesPerPixel(); + const u32 src_bpp{params.GetBytesPerPixel()}; + const u32 dst_bpp{rhs.GetBytesPerPixel()}; return std::tie(src_bpp, params.is_tiled) == std::tie(dst_bpp, rhs.is_tiled); } MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const { - if (params.is_tiled) { - if (std::tie(params.height, params.depth, params.block_width, params.block_height, - params.block_depth, params.tile_width_spacing) == - std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, - rhs.tile_width_spacing)) { - if (params.width == rhs.width) { - return MatchStructureResult::FullMatch; - } - if (params.GetBlockAlignedWidth() == rhs.GetBlockAlignedWidth()) { - return MatchStructureResult::SemiMatch; - } - } - return MatchStructureResult::None; - } else { + if (!params.is_tiled) { if (std::tie(params.width, params.height, params.pitch) == std::tie(rhs.width, rhs.height, rhs.pitch)) { return MatchStructureResult::FullMatch; } return MatchStructureResult::None; } + // Tiled surface + if (std::tie(params.height, params.depth, params.block_width, params.block_height, + params.block_depth, params.tile_width_spacing) == + std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, + rhs.tile_width_spacing)) { + if (params.width == rhs.width) { + return MatchStructureResult::FullMatch; + } + if (params.GetBlockAlignedWidth() == rhs.GetBlockAlignedWidth()) { + return MatchStructureResult::SemiMatch; + } + } + return MatchStructureResult::None; } std::optional> GetLayerMipmap(const GPUVAddr candidate_gpu_addr) const { @@ -151,35 +151,7 @@ public: } std::vector BreakDown(const SurfaceParams& in_params) const { - std::vector result; - const u32 layers{params.depth}; - const u32 mipmaps{params.num_levels}; - - if (params.is_layered) { - result.reserve(static_cast(layers) * static_cast(mipmaps)); - for (u32 layer = 0; layer < layers; layer++) { - const u32 layer_offset{layer * mipmaps}; - for (u32 level = 0; level < mipmaps; level++) { - const u32 width{ - std::min(params.GetMipWidth(level), in_params.GetMipWidth(level))}; - const u32 height{ - std::min(params.GetMipHeight(level), in_params.GetMipHeight(level))}; - result.emplace_back(width, height, layer, level); - } - } - return result; - - } else { - result.reserve(mipmaps); - for (u32 level = 0; level < mipmaps; level++) { - const u32 width{std::min(params.GetMipWidth(level), in_params.GetMipWidth(level))}; - const u32 height{ - std::min(params.GetMipHeight(level), in_params.GetMipHeight(level))}; - const u32 depth{std::min(params.GetMipDepth(level), in_params.GetMipDepth(level))}; - result.emplace_back(width, height, depth, level); - } - return result; - } + return params.is_layered ? BreakDownLayered(in_params) : BreakDownNonLayered(in_params); } protected: @@ -203,6 +175,37 @@ protected: private: void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer, u32 level); + + std::vector BreakDownLayered(const SurfaceParams& in_params) const { + const u32 layers{params.depth}; + const u32 mipmaps{params.num_levels}; + std::vector result; + result.reserve(static_cast(layers) * static_cast(mipmaps)); + + for (u32 layer = 0; layer < layers; layer++) { + for (u32 level = 0; level < mipmaps; level++) { + const u32 width{std::min(params.GetMipWidth(level), in_params.GetMipWidth(level))}; + const u32 height{ + std::min(params.GetMipHeight(level), in_params.GetMipHeight(level))}; + result.emplace_back(width, height, layer, level); + } + } + return result; + } + + std::vector BreakDownNonLayered(const SurfaceParams& in_params) const { + const u32 mipmaps{params.num_levels}; + std::vector result; + result.reserve(mipmaps); + + for (u32 level = 0; level < mipmaps; level++) { + const u32 width{std::min(params.GetMipWidth(level), in_params.GetMipWidth(level))}; + const u32 height{std::min(params.GetMipHeight(level), in_params.GetMipHeight(level))}; + const u32 depth{std::min(params.GetMipDepth(level), in_params.GetMipDepth(level))}; + result.emplace_back(width, height, depth, level); + } + return result; + } }; template -- cgit v1.2.3 From 549fd18ac44c6bcefdf6584484d775f0129e3fe3 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 7 May 2019 22:03:33 -0300 Subject: surface_view: Add constructor for ViewParams --- src/video_core/texture_cache/surface_base.h | 39 +++++++++-------------------- 1 file changed, 12 insertions(+), 27 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 0cfb835d9..f469ab498 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -253,45 +253,30 @@ public: } TView EmplaceOverview(const SurfaceParams& overview_params) { - ViewParams vp{}; - vp.base_level = 0; - vp.num_levels = params.num_levels; - vp.target = overview_params.target; - if (params.is_layered && !overview_params.is_layered) { - vp.base_layer = 0; - vp.num_layers = 1; - } else { - vp.base_layer = 0; - vp.num_layers = params.depth; - } - return GetView(vp); + const u32 num_layers{params.is_layered && !overview_params.is_layered ? 1 : params.depth}; + const ViewParams view_params(overview_params.target, 0, num_layers, 0, params.num_levels); + return GetView(view_params); } std::optional EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { - if (view_addr < gpu_addr) - return {}; - if (params.target == SurfaceTarget::Texture3D || + if (view_addr < gpu_addr || params.target == SurfaceTarget::Texture3D || view_params.target == SurfaceTarget::Texture3D) { return {}; } - const std::size_t size = view_params.GetGuestSizeInBytes(); - auto layer_mipmap = GetLayerMipmap(view_addr); + const std::size_t size{view_params.GetGuestSizeInBytes()}; + const auto layer_mipmap{GetLayerMipmap(view_addr)}; if (!layer_mipmap) { return {}; } - const u32 layer = (*layer_mipmap).first; - const u32 mipmap = (*layer_mipmap).second; + const u32 layer{layer_mipmap->first}; + const u32 mipmap{layer_mipmap->second}; if (GetMipmapSize(mipmap) != size) { - // TODO: the view may cover many mimaps, this case can still go on + // TODO: The view may cover many mimaps, this case can still go on. + // This edge-case can be safely be ignored since it will just result in worse + // performance. return {}; } - ViewParams vp{}; - vp.base_layer = layer; - vp.num_layers = 1; - vp.base_level = mipmap; - vp.num_levels = 1; - vp.target = view_params.target; - return {GetView(vp)}; + return GetView(ViewParams(params.target, layer, 1, mipmap, 1)); } TView GetMainView() const { -- cgit v1.2.3 From e0002599accc783be1bda5853df377c84ee6219a Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 8 May 2019 03:51:54 -0300 Subject: surface_base: Add parenthesis to EmplaceOverview's predicate --- src/video_core/texture_cache/surface_base.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index f469ab498..c11998249 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -253,9 +253,8 @@ public: } TView EmplaceOverview(const SurfaceParams& overview_params) { - const u32 num_layers{params.is_layered && !overview_params.is_layered ? 1 : params.depth}; - const ViewParams view_params(overview_params.target, 0, num_layers, 0, params.num_levels); - return GetView(view_params); + const u32 num_layers{(params.is_layered && !overview_params.is_layered) ? 1 : params.depth}; + return GetView(ViewParams(overview_params.target, 0, num_layers, 0, params.num_levels)); } std::optional EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { -- cgit v1.2.3 From de0b1cb2b2199bd8efff78938d385fa74652cdfb Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 8 May 2019 07:09:02 -0400 Subject: Fixes to mipmap's process and reconstruct process --- src/video_core/texture_cache/surface_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index c11998249..017ee999e 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -262,20 +262,20 @@ public: view_params.target == SurfaceTarget::Texture3D) { return {}; } - const std::size_t size{view_params.GetGuestSizeInBytes()}; const auto layer_mipmap{GetLayerMipmap(view_addr)}; if (!layer_mipmap) { return {}; } const u32 layer{layer_mipmap->first}; const u32 mipmap{layer_mipmap->second}; + const std::size_t size{view_params.GetGuestSizeInBytes()}; if (GetMipmapSize(mipmap) != size) { // TODO: The view may cover many mimaps, this case can still go on. // This edge-case can be safely be ignored since it will just result in worse // performance. return {}; } - return GetView(ViewParams(params.target, layer, 1, mipmap, 1)); + return GetView(ViewParams(view_params.target, layer, 1, mipmap, 1)); } TView GetMainView() const { -- cgit v1.2.3 From 4e2071b6d9b414fa0152deb5e9d55674d636afe4 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 8 May 2019 17:45:59 -0400 Subject: texture_cache: Correct premature texceptions Due to our current infrastructure, it is possible for a mipmap to be set on as a render target before a texception of that mipmap's superset be set afterwards. This is problematic as we rely on texture views to set up texceptions and protecting render targets targets for 3D texture rendering. One simple solution is to configure framebuffers after texture setup but this brings other problems. This solution, forces a reconfiguration of the framebuffers after such event happens. --- src/video_core/texture_cache/surface_base.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 017ee999e..179e80ddb 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -55,6 +55,11 @@ public: return (cache_addr < end) && (cache_addr_end > start); } + bool IsInside(const GPUVAddr other_start, const GPUVAddr other_end) { + const GPUVAddr gpu_addr_end = gpu_addr + guest_memory_size; + return (gpu_addr <= other_start && other_end <= gpu_addr_end); + } + // Use only when recycling a surface void SetGpuAddr(const GPUVAddr new_addr) { gpu_addr = new_addr; @@ -105,6 +110,12 @@ public: return params.target == target; } + bool MatchesSubTexture(const SurfaceParams& rhs, const GPUVAddr other_gpu_addr) const { + return std::tie(gpu_addr, params.target, params.num_levels) == + std::tie(other_gpu_addr, rhs.target, rhs.num_levels) && + params.target == SurfaceTarget::Texture2D && params.num_levels == 1; + } + bool MatchesTopology(const SurfaceParams& rhs) const { const u32 src_bpp{params.GetBytesPerPixel()}; const u32 dst_bpp{rhs.GetBytesPerPixel()}; @@ -121,9 +132,9 @@ public: } // Tiled surface if (std::tie(params.height, params.depth, params.block_width, params.block_height, - params.block_depth, params.tile_width_spacing) == + params.block_depth, params.tile_width_spacing, params.num_levels) == std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, - rhs.tile_width_spacing)) { + rhs.tile_width_spacing, rhs.num_levels)) { if (params.width == rhs.width) { return MatchStructureResult::FullMatch; } @@ -259,7 +270,7 @@ public: std::optional EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { if (view_addr < gpu_addr || params.target == SurfaceTarget::Texture3D || - view_params.target == SurfaceTarget::Texture3D) { + params.num_levels == 1 || view_params.target == SurfaceTarget::Texture3D) { return {}; } const auto layer_mipmap{GetLayerMipmap(view_addr)}; -- cgit v1.2.3 From b347543e8341ae323ea232d47df2c144fe21c739 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 8 May 2019 18:27:29 -0400 Subject: Reduce amount of size calculations. --- src/video_core/texture_cache/surface_base.h | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 179e80ddb..095deb602 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -9,6 +9,7 @@ #include #include "common/assert.h" +#include "common/common_funcs.h" #include "common/common_types.h" #include "video_core/gpu.h" #include "video_core/morton.h" @@ -16,16 +17,6 @@ #include "video_core/texture_cache/surface_params.h" #include "video_core/texture_cache/surface_view.h" -template > -ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, Compare comp = {}) { - // Note: BOTH type T and the type after ForwardIt is dereferenced - // must be implicitly convertible to BOTH Type1 and Type2, used in Compare. - // This is stricter than lower_bound requirement (see above) - - first = std::lower_bound(first, last, value, comp); - return first != last && !comp(value, *first) ? first : last; -} - namespace Tegra { class MemoryManager; } @@ -153,7 +144,7 @@ public: const auto layer{static_cast(relative_address / layer_size)}; const GPUVAddr mipmap_address = relative_address - layer_size * layer; const auto mipmap_it = - binary_find(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); + Common::BinaryFind(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); if (mipmap_it == mipmap_offsets.end()) { return {}; } @@ -172,8 +163,8 @@ protected: virtual void DecorateSurfaceName() = 0; const SurfaceParams params; - const std::size_t layer_size; - const std::size_t guest_memory_size; + std::size_t layer_size; + std::size_t guest_memory_size; const std::size_t host_memory_size; GPUVAddr gpu_addr{}; CacheAddr cache_addr{}; @@ -268,9 +259,11 @@ public: return GetView(ViewParams(overview_params.target, 0, num_layers, 0, params.num_levels)); } - std::optional EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr) { - if (view_addr < gpu_addr || params.target == SurfaceTarget::Texture3D || - params.num_levels == 1 || view_params.target == SurfaceTarget::Texture3D) { + std::optional EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr, + const std::size_t candidate_size) { + if (params.target == SurfaceTarget::Texture3D || + (params.num_levels == 1 && !params.is_layered) || + view_params.target == SurfaceTarget::Texture3D) { return {}; } const auto layer_mipmap{GetLayerMipmap(view_addr)}; @@ -279,8 +272,7 @@ public: } const u32 layer{layer_mipmap->first}; const u32 mipmap{layer_mipmap->second}; - const std::size_t size{view_params.GetGuestSizeInBytes()}; - if (GetMipmapSize(mipmap) != size) { + if (GetMipmapSize(mipmap) != candidate_size) { // TODO: The view may cover many mimaps, this case can still go on. // This edge-case can be safely be ignored since it will just result in worse // performance. -- cgit v1.2.3 From 1bbc9debfbcbd960874e2f877604506d174f613c Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 10 May 2019 23:42:08 -0400 Subject: Remove Framebuffer reconfiguration and restrict rendertarget protection --- src/video_core/texture_cache/surface_base.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 095deb602..78db2d665 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -218,12 +218,12 @@ public: virtual void DownloadTexture(std::vector& staging_buffer) = 0; void MarkAsModified(const bool is_modified_, const u64 tick) { - is_modified = is_modified_ || is_protected; + is_modified = is_modified_ || is_target; modification_tick = tick; } - void MarkAsProtected(const bool is_protected) { - this->is_protected = is_protected; + void MarkAsRenderTarget(const bool is_target) { + this->is_target = is_target; } void MarkAsPicked(const bool is_picked) { @@ -235,7 +235,12 @@ public: } bool IsProtected() const { - return is_protected; + // Only 3D Slices are to be protected + return is_target && params.block_depth > 0; + } + + bool IsRenderTarget() const { + return is_target; } bool IsRegistered() const { @@ -307,7 +312,7 @@ private: } bool is_modified{}; - bool is_protected{}; + bool is_target{}; bool is_registered{}; bool is_picked{}; u64 modification_tick{}; -- cgit v1.2.3 From 7731a0e2d15da04eea746b4b8dd5c6c4b29f9f29 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 12 May 2019 20:33:52 -0400 Subject: texture_cache: General Fixes Fixed ASTC mipmaps loading Fixed alignment on openGL upload/download Fixed Block Height Calculation Removed unalign_height --- src/video_core/texture_cache/surface_base.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/video_core/texture_cache/surface_base.h') 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: return mipmap_sizes[level]; } + bool IsLinear() const { + return !params.is_tiled; + } + bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const { return params.pixel_format == pixel_format; } -- cgit v1.2.3 From 175aa343ff1c9f931b266caf2d19b8df943dab0d Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 18 May 2019 04:57:49 -0400 Subject: texture_cache: Fermi2D reform and implement View Mirage This also does some fixes on compressed textures reinterpret and on the Fermi2D engine in general. --- src/video_core/texture_cache/surface_base.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index cb7f22706..a3dd1c607 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -126,14 +126,19 @@ public: return MatchStructureResult::None; } // Tiled surface - if (std::tie(params.height, params.depth, params.block_width, params.block_height, - params.block_depth, params.tile_width_spacing, params.num_levels) == - std::tie(rhs.height, rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, + if (std::tie(params.depth, params.block_width, params.block_height, params.block_depth, + params.tile_width_spacing, params.num_levels) == + std::tie(rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, rhs.tile_width_spacing, rhs.num_levels)) { - if (params.width == rhs.width) { + if (std::tie(params.width, params.height) == std::tie(rhs.width, rhs.height)) { return MatchStructureResult::FullMatch; } - if (params.GetBlockAlignedWidth() == rhs.GetBlockAlignedWidth()) { + const u32 ws = SurfaceParams::ConvertWidth(rhs.GetBlockAlignedWidth(), + params.pixel_format, rhs.pixel_format); + const u32 hs = + SurfaceParams::ConvertHeight(rhs.height, params.pixel_format, rhs.pixel_format); + const u32 w1 = params.GetBlockAlignedWidth(); + if (std::tie(w1, params.height) == std::tie(ws, hs)) { return MatchStructureResult::SemiMatch; } } -- cgit v1.2.3 From fcac55d5bff025fee822c2e7b0e06cdc178143dc Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 21 May 2019 07:56:53 -0400 Subject: texture_cache: Add checks for texture buffers. --- src/video_core/texture_cache/surface_base.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index a3dd1c607..210f27907 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -114,10 +114,23 @@ public: bool MatchesTopology(const SurfaceParams& rhs) const { const u32 src_bpp{params.GetBytesPerPixel()}; const u32 dst_bpp{rhs.GetBytesPerPixel()}; - return std::tie(src_bpp, params.is_tiled) == std::tie(dst_bpp, rhs.is_tiled); + const bool ib1 = params.IsBuffer(); + const bool ib2 = rhs.IsBuffer(); + return std::tie(src_bpp, params.is_tiled, ib1) == std::tie(dst_bpp, rhs.is_tiled, ib2); } MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const { + // Buffer surface Check + if (params.IsBuffer()) { + const std::size_t wd1 = params.width*params.GetBytesPerPixel(); + const std::size_t wd2 = rhs.width*rhs.GetBytesPerPixel(); + if (wd1 == wd2) { + return MatchStructureResult::FullMatch; + } + return MatchStructureResult::None; + } + + // Linear Surface check if (!params.is_tiled) { if (std::tie(params.width, params.height, params.pitch) == std::tie(rhs.width, rhs.height, rhs.pitch)) { @@ -125,7 +138,8 @@ public: } return MatchStructureResult::None; } - // Tiled surface + + // Tiled Surface check if (std::tie(params.depth, params.block_width, params.block_height, params.block_depth, params.tile_width_spacing, params.num_levels) == std::tie(rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, -- cgit v1.2.3 From bdf9faab331cd79ca5c5e51c2369fc801e8cecea Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 21 May 2019 11:24:20 -0400 Subject: texture_cache: Handle uncontinuous surfaces. --- src/video_core/texture_cache/surface_base.h | 34 +++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 210f27907..dacbc97c7 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -32,11 +32,28 @@ enum class MatchStructureResult : u32 { None = 2, }; +class StagingCache { +public: + StagingCache() {} + ~StagingCache() = default; + + std::vector& GetBuffer(std::size_t index) { + return staging_buffer[index]; + } + + void SetSize(std::size_t size) { + staging_buffer.resize(size); + } + +private: + std::vector> staging_buffer; +}; + class SurfaceBaseImpl { public: - void LoadBuffer(Tegra::MemoryManager& memory_manager, std::vector& staging_buffer); + void LoadBuffer(Tegra::MemoryManager& memory_manager, StagingCache& staging_cache); - void FlushBuffer(Tegra::MemoryManager& memory_manager, std::vector& staging_buffer); + void FlushBuffer(Tegra::MemoryManager& memory_manager, StagingCache& staging_cache); GPUVAddr GetGpuAddr() const { return gpu_addr; @@ -93,6 +110,14 @@ public: return mipmap_sizes[level]; } + void MarkAsContinuous(const bool is_continuous) { + this->is_continuous = is_continuous; + } + + bool IsContinuous() const { + return is_continuous; + } + bool IsLinear() const { return !params.is_tiled; } @@ -122,8 +147,8 @@ public: MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const { // Buffer surface Check if (params.IsBuffer()) { - const std::size_t wd1 = params.width*params.GetBytesPerPixel(); - const std::size_t wd2 = rhs.width*rhs.GetBytesPerPixel(); + const std::size_t wd1 = params.width * params.GetBytesPerPixel(); + const std::size_t wd2 = rhs.width * rhs.GetBytesPerPixel(); if (wd1 == wd2) { return MatchStructureResult::FullMatch; } @@ -193,6 +218,7 @@ protected: CacheAddr cache_addr{}; CacheAddr cache_addr_end{}; VAddr cpu_addr{}; + bool is_continuous{}; std::vector mipmap_sizes; std::vector mipmap_offsets; -- cgit v1.2.3 From 92513541529e90f4f79a1f2c3f8ccf5a199e4c20 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 24 May 2019 11:59:23 -0400 Subject: texture_cache: Correct copying between compressed and uncompressed formats --- src/video_core/texture_cache/surface_base.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index dacbc97c7..77c2d6758 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -235,9 +235,8 @@ private: for (u32 layer = 0; layer < layers; layer++) { for (u32 level = 0; level < mipmaps; level++) { - const u32 width{std::min(params.GetMipWidth(level), in_params.GetMipWidth(level))}; - const u32 height{ - std::min(params.GetMipHeight(level), in_params.GetMipHeight(level))}; + const u32 width = SurfaceParams::IntersectWidth(params, in_params, level, level); + const u32 height = SurfaceParams::IntersectHeight(params, in_params, level, level); result.emplace_back(width, height, layer, level); } } @@ -250,8 +249,8 @@ private: result.reserve(mipmaps); for (u32 level = 0; level < mipmaps; level++) { - const u32 width{std::min(params.GetMipWidth(level), in_params.GetMipWidth(level))}; - const u32 height{std::min(params.GetMipHeight(level), in_params.GetMipHeight(level))}; + const u32 width = SurfaceParams::IntersectWidth(params, in_params, level, level); + const u32 height = SurfaceParams::IntersectHeight(params, in_params, level, level); const u32 depth{std::min(params.GetMipDepth(level), in_params.GetMipDepth(level))}; result.emplace_back(width, height, depth, level); } -- cgit v1.2.3 From 228f516bb4426a41a4d1c1756751557f7a0eecda Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 24 May 2019 15:34:31 -0400 Subject: texture_cache uncompress-compress is untopological. This makes conflicts between non compress and compress textures to be auto recycled. It also limits the amount of mipmaps a texture can have if it goes above it's limit. --- src/video_core/texture_cache/surface_base.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 77c2d6758..70b5258c9 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -32,6 +32,12 @@ enum class MatchStructureResult : u32 { None = 2, }; +enum class MatchTopologyResult : u32 { + FullMatch = 0, + CompressUnmatch = 1, + None = 2, +}; + class StagingCache { public: StagingCache() {} @@ -136,12 +142,20 @@ public: params.target == SurfaceTarget::Texture2D && params.num_levels == 1; } - bool MatchesTopology(const SurfaceParams& rhs) const { + MatchTopologyResult MatchesTopology(const SurfaceParams& rhs) const { const u32 src_bpp{params.GetBytesPerPixel()}; const u32 dst_bpp{rhs.GetBytesPerPixel()}; const bool ib1 = params.IsBuffer(); const bool ib2 = rhs.IsBuffer(); - return std::tie(src_bpp, params.is_tiled, ib1) == std::tie(dst_bpp, rhs.is_tiled, ib2); + if (std::tie(src_bpp, params.is_tiled, ib1) == std::tie(dst_bpp, rhs.is_tiled, ib2)) { + const bool cb1 = params.IsCompressed(); + const bool cb2 = rhs.IsCompressed(); + if (cb1 == cb2) { + return MatchTopologyResult::FullMatch; + } + return MatchTopologyResult::CompressUnmatch; + } + return MatchTopologyResult::None; } MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const { -- cgit v1.2.3 From 9f755218a1359cbd004e6c287f5fead0897c1d11 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 1 Jun 2019 23:03:22 -0400 Subject: texture_cache: move some large methods to cpp files --- src/video_core/texture_cache/surface_base.h | 106 ++-------------------------- 1 file changed, 7 insertions(+), 99 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 70b5258c9..9d19ecd5f 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -136,83 +136,17 @@ public: return params.target == target; } + MatchTopologyResult MatchesTopology(const SurfaceParams& rhs) const; + + MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const; + bool MatchesSubTexture(const SurfaceParams& rhs, const GPUVAddr other_gpu_addr) const { return std::tie(gpu_addr, params.target, params.num_levels) == std::tie(other_gpu_addr, rhs.target, rhs.num_levels) && params.target == SurfaceTarget::Texture2D && params.num_levels == 1; } - MatchTopologyResult MatchesTopology(const SurfaceParams& rhs) const { - const u32 src_bpp{params.GetBytesPerPixel()}; - const u32 dst_bpp{rhs.GetBytesPerPixel()}; - const bool ib1 = params.IsBuffer(); - const bool ib2 = rhs.IsBuffer(); - if (std::tie(src_bpp, params.is_tiled, ib1) == std::tie(dst_bpp, rhs.is_tiled, ib2)) { - const bool cb1 = params.IsCompressed(); - const bool cb2 = rhs.IsCompressed(); - if (cb1 == cb2) { - return MatchTopologyResult::FullMatch; - } - return MatchTopologyResult::CompressUnmatch; - } - return MatchTopologyResult::None; - } - - MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const { - // Buffer surface Check - if (params.IsBuffer()) { - const std::size_t wd1 = params.width * params.GetBytesPerPixel(); - const std::size_t wd2 = rhs.width * rhs.GetBytesPerPixel(); - if (wd1 == wd2) { - return MatchStructureResult::FullMatch; - } - return MatchStructureResult::None; - } - - // Linear Surface check - if (!params.is_tiled) { - if (std::tie(params.width, params.height, params.pitch) == - std::tie(rhs.width, rhs.height, rhs.pitch)) { - return MatchStructureResult::FullMatch; - } - return MatchStructureResult::None; - } - - // Tiled Surface check - if (std::tie(params.depth, params.block_width, params.block_height, params.block_depth, - params.tile_width_spacing, params.num_levels) == - std::tie(rhs.depth, rhs.block_width, rhs.block_height, rhs.block_depth, - rhs.tile_width_spacing, rhs.num_levels)) { - if (std::tie(params.width, params.height) == std::tie(rhs.width, rhs.height)) { - return MatchStructureResult::FullMatch; - } - const u32 ws = SurfaceParams::ConvertWidth(rhs.GetBlockAlignedWidth(), - params.pixel_format, rhs.pixel_format); - const u32 hs = - SurfaceParams::ConvertHeight(rhs.height, params.pixel_format, rhs.pixel_format); - const u32 w1 = params.GetBlockAlignedWidth(); - if (std::tie(w1, params.height) == std::tie(ws, hs)) { - return MatchStructureResult::SemiMatch; - } - } - return MatchStructureResult::None; - } - - std::optional> GetLayerMipmap(const GPUVAddr candidate_gpu_addr) const { - if (candidate_gpu_addr < gpu_addr) { - return {}; - } - const auto relative_address{static_cast(candidate_gpu_addr - gpu_addr)}; - const auto layer{static_cast(relative_address / layer_size)}; - const GPUVAddr mipmap_address = relative_address - layer_size * layer; - const auto mipmap_it = - Common::BinaryFind(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); - if (mipmap_it == mipmap_offsets.end()) { - return {}; - } - const auto level{static_cast(std::distance(mipmap_offsets.begin(), mipmap_it))}; - return std::make_pair(layer, level); - } + std::optional> GetLayerMipmap(const GPUVAddr candidate_gpu_addr) const; std::vector BreakDown(const SurfaceParams& in_params) const { return params.is_layered ? BreakDownLayered(in_params) : BreakDownNonLayered(in_params); @@ -241,35 +175,9 @@ private: void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer, u32 level); - std::vector BreakDownLayered(const SurfaceParams& in_params) const { - const u32 layers{params.depth}; - const u32 mipmaps{params.num_levels}; - std::vector result; - result.reserve(static_cast(layers) * static_cast(mipmaps)); - - for (u32 layer = 0; layer < layers; layer++) { - for (u32 level = 0; level < mipmaps; level++) { - const u32 width = SurfaceParams::IntersectWidth(params, in_params, level, level); - const u32 height = SurfaceParams::IntersectHeight(params, in_params, level, level); - result.emplace_back(width, height, layer, level); - } - } - return result; - } - - std::vector BreakDownNonLayered(const SurfaceParams& in_params) const { - const u32 mipmaps{params.num_levels}; - std::vector result; - result.reserve(mipmaps); + std::vector BreakDownLayered(const SurfaceParams& in_params) const; - for (u32 level = 0; level < mipmaps; level++) { - const u32 width = SurfaceParams::IntersectWidth(params, in_params, level, level); - const u32 height = SurfaceParams::IntersectHeight(params, in_params, level, level); - const u32 depth{std::min(params.GetMipDepth(level), in_params.GetMipDepth(level))}; - result.emplace_back(width, height, depth, level); - } - return result; - } + std::vector BreakDownNonLayered(const SurfaceParams& in_params) const; }; template -- cgit v1.2.3 From 2d83553ea7ab2629e7e1a83cc3345c0115d69453 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 13 Jun 2019 09:46:36 -0400 Subject: texture_cache: Implement siblings texture formats. --- src/video_core/texture_cache/surface_base.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 9d19ecd5f..58265e9d3 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -132,6 +132,10 @@ public: return params.pixel_format == pixel_format; } + VideoCore::Surface::PixelFormat GetFormat() const { + return params.pixel_format; + } + bool MatchTarget(VideoCore::Surface::SurfaceTarget target) const { return params.target == target; } -- cgit v1.2.3 From fed773a86c96fc62f18181a1d3ba410b25c2edee Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 14 Jun 2019 18:40:06 -0400 Subject: texture_cache: Implement Irregular Views in surfaces --- src/video_core/texture_cache/surface_base.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 58265e9d3..662221adc 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -238,6 +238,26 @@ public: return GetView(ViewParams(overview_params.target, 0, num_layers, 0, params.num_levels)); } + std::optional EmplaceIrregularView(const SurfaceParams& view_params, + const GPUVAddr view_addr, + const std::size_t candidate_size, const u32 mipmap, + const u32 layer) { + const auto layer_mipmap{GetLayerMipmap(view_addr + candidate_size)}; + if (!layer_mipmap) { + return {}; + } + const u32 end_layer{layer_mipmap->first}; + const u32 end_mipmap{layer_mipmap->second}; + if (layer != end_layer) { + if (mipmap == 0 && end_mipmap == 0) { + return GetView(ViewParams(view_params.target, layer, end_layer - layer + 1, 0, 1)); + } + return {}; + } else { + return GetView(ViewParams(view_params.target, layer, 1, mipmap, end_mipmap - mipmap + 1)); + } + } + std::optional EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr, const std::size_t candidate_size) { if (params.target == SurfaceTarget::Texture3D || @@ -252,10 +272,7 @@ public: const u32 layer{layer_mipmap->first}; const u32 mipmap{layer_mipmap->second}; if (GetMipmapSize(mipmap) != candidate_size) { - // TODO: The view may cover many mimaps, this case can still go on. - // This edge-case can be safely be ignored since it will just result in worse - // performance. - return {}; + return EmplaceIrregularView(view_params, view_addr, candidate_size, mipmap, layer); } return GetView(ViewParams(view_params.target, layer, 1, mipmap, 1)); } -- cgit v1.2.3 From d1812316e1b0f03af2ba10d4fe04be728e72725c Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 20 Jun 2019 21:22:20 -0400 Subject: texture_cache: Style and Corrections --- src/video_core/texture_cache/surface_base.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 662221adc..252b18538 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -254,7 +254,8 @@ public: } return {}; } else { - return GetView(ViewParams(view_params.target, layer, 1, mipmap, end_mipmap - mipmap + 1)); + return GetView( + ViewParams(view_params.target, layer, 1, mipmap, end_mipmap - mipmap + 1)); } } -- cgit v1.2.3 From 0837290992e0873f270cd032d2d0e5b91b643267 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 24 Jun 2019 02:08:52 -0300 Subject: texture_cache/surface_base: Address feedback --- src/video_core/texture_cache/surface_base.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index 252b18538..d632630ce 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -40,13 +40,17 @@ enum class MatchTopologyResult : u32 { class StagingCache { public: - StagingCache() {} - ~StagingCache() = default; + explicit StagingCache(); + ~StagingCache(); std::vector& GetBuffer(std::size_t index) { return staging_buffer[index]; } + const std::vector& GetBuffer(std::size_t index) const { + return staging_buffer[index]; + } + void SetSize(std::size_t size) { staging_buffer.resize(size); } -- cgit v1.2.3 From 3f3c3ca5f96fd5742524703f20b531338fa2e5f7 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 29 Jun 2019 17:29:39 -0300 Subject: texture_cache: Address feedback --- src/video_core/texture_cache/surface_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index d632630ce..eaed6545d 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -294,8 +294,8 @@ protected: virtual TView CreateView(const ViewParams& view_key) = 0; - std::unordered_map views; TView main_view; + std::unordered_map views; private: TView GetView(const ViewParams& key) { -- cgit v1.2.3 From 3b9d89839dc62e9e63a3cbe9636cf85276babdfb Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 4 Jul 2019 21:10:59 -0400 Subject: texture_cache: Address Feedback --- src/video_core/texture_cache/surface_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/video_core/texture_cache/surface_base.h') diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h index eaed6545d..8ba386a8a 100644 --- a/src/video_core/texture_cache/surface_base.h +++ b/src/video_core/texture_cache/surface_base.h @@ -9,7 +9,7 @@ #include #include "common/assert.h" -#include "common/common_funcs.h" +#include "common/binary_find.h" #include "common/common_types.h" #include "video_core/gpu.h" #include "video_core/morton.h" @@ -191,7 +191,7 @@ private: template class SurfaceBase : public SurfaceBaseImpl { public: - virtual void UploadTexture(std::vector& staging_buffer) = 0; + virtual void UploadTexture(const std::vector& staging_buffer) = 0; virtual void DownloadTexture(std::vector& staging_buffer) = 0; -- cgit v1.2.3