diff options
Diffstat (limited to 'src/video_core/texture_cache.cpp')
| -rw-r--r-- | src/video_core/texture_cache.cpp | 110 |
1 files changed, 109 insertions, 1 deletions
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; |