rasterizer_cache: Fixes to (unaligned) texture downloads (#6697)
* rasterizer_cache: Header cleanup * gl_texture_runtime: Fix incorrect stride in single scanline downloads * texture_codec: Fix unaligned texture downloads
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include "core/memory.h"
|
||||
#include "video_core/custom_textures/custom_tex_manager.h"
|
||||
#include "video_core/rasterizer_cache/rasterizer_cache_base.h"
|
||||
#include "video_core/rasterizer_cache/surface_base.h"
|
||||
#include "video_core/regs.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/texture/texture_decode.h"
|
||||
@@ -1212,7 +1213,7 @@ void RasterizerCache<T>::ClearAll(bool flush) {
|
||||
|
||||
// Remove the whole cache without really looking at it.
|
||||
cached_pages -= flush_interval;
|
||||
dirty_regions -= SurfaceInterval(0x0, 0xFFFFFFFF);
|
||||
dirty_regions.clear();
|
||||
page_table.clear();
|
||||
remove_surfaces.clear();
|
||||
}
|
||||
|
@@ -11,7 +11,8 @@
|
||||
#include <boost/icl/interval_map.hpp>
|
||||
#include <tsl/robin_map.h>
|
||||
#include "video_core/rasterizer_cache/sampler_params.h"
|
||||
#include "video_core/rasterizer_cache/surface_base.h"
|
||||
#include "video_core/rasterizer_cache/surface_params.h"
|
||||
#include "video_core/rasterizer_cache/texture_cube.h"
|
||||
|
||||
namespace Memory {
|
||||
class MemorySystem;
|
||||
@@ -70,12 +71,6 @@ class RasterizerCache {
|
||||
SurfaceId depth_id;
|
||||
};
|
||||
|
||||
struct TextureCube {
|
||||
SurfaceId surface_id;
|
||||
std::array<SurfaceId, 6> face_ids;
|
||||
std::array<u64, 6> ticks;
|
||||
};
|
||||
|
||||
public:
|
||||
explicit RasterizerCache(Memory::MemorySystem& memory, CustomTexManager& custom_tex_manager,
|
||||
Runtime& runtime, Pica::Regs& regs, RendererBase& renderer);
|
||||
|
21
src/video_core/rasterizer_cache/slot_id.h
Normal file
21
src/video_core/rasterizer_cache/slot_id.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/slot_vector.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
using SurfaceId = Common::SlotId;
|
||||
using SamplerId = Common::SlotId;
|
||||
|
||||
/// Fake surface ID for null surfaces
|
||||
constexpr SurfaceId NULL_SURFACE_ID{0};
|
||||
/// Fake surface ID for null cube surfaces
|
||||
constexpr SurfaceId NULL_SURFACE_CUBE_ID{1};
|
||||
/// Fake sampler ID for null samplers
|
||||
constexpr SamplerId NULL_SAMPLER_ID{0};
|
||||
|
||||
} // namespace VideoCore
|
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <span>
|
||||
@@ -264,6 +265,7 @@ static constexpr void MortonCopy(u32 width, u32 height, u32 start_offset, u32 en
|
||||
const u32 aligned_down_start_offset = Common::AlignDown(start_offset, tile_size);
|
||||
const u32 aligned_start_offset = Common::AlignUp(start_offset, tile_size);
|
||||
const u32 aligned_end_offset = Common::AlignDown(end_offset, tile_size);
|
||||
const u32 begin_pixel_index = aligned_down_start_offset * 8 / GetFormatBpp(format);
|
||||
|
||||
ASSERT(!morton_to_linear ||
|
||||
(aligned_start_offset == start_offset && aligned_end_offset == end_offset));
|
||||
@@ -271,12 +273,12 @@ static constexpr void MortonCopy(u32 width, u32 height, u32 start_offset, u32 en
|
||||
// In OpenGL the texture origin is in the bottom left corner as opposed to other
|
||||
// APIs that have it at the top left. To avoid flipping texture coordinates in
|
||||
// the shader we read/write the linear buffer from the bottom up
|
||||
u32 linear_offset = ((height - 8) * width) * aligned_bytes_per_pixel;
|
||||
u32 x = (begin_pixel_index % (width * 8)) / 8;
|
||||
u32 y = (begin_pixel_index / (width * 8)) * 8;
|
||||
u32 linear_offset = ((height - 8 - y) * width + x) * aligned_bytes_per_pixel;
|
||||
u32 tiled_offset = 0;
|
||||
u32 x = 0;
|
||||
u32 y = 0;
|
||||
|
||||
const auto LinearNextTile = [&] {
|
||||
const auto linear_next_tile = [&] {
|
||||
x = (x + 8) % width;
|
||||
linear_offset += 8 * aligned_bytes_per_pixel;
|
||||
if (!x) {
|
||||
@@ -300,7 +302,7 @@ static constexpr void MortonCopy(u32 width, u32 height, u32 start_offset, u32 en
|
||||
std::min(aligned_start_offset, end_offset) - start_offset);
|
||||
|
||||
tiled_offset += aligned_start_offset - start_offset;
|
||||
LinearNextTile();
|
||||
linear_next_tile();
|
||||
}
|
||||
|
||||
// If the copy spans multiple tiles, copy the fully aligned tiles in between.
|
||||
@@ -313,7 +315,7 @@ static constexpr void MortonCopy(u32 width, u32 height, u32 start_offset, u32 en
|
||||
auto tiled_data = tiled_buffer.subspan(tiled_offset, tile_size);
|
||||
MortonCopyTile<morton_to_linear, format, converted>(width, tiled_data, linear_data);
|
||||
tiled_offset += tile_size;
|
||||
LinearNextTile();
|
||||
linear_next_tile();
|
||||
}
|
||||
}
|
||||
|
||||
|
52
src/video_core/rasterizer_cache/texture_cube.h
Normal file
52
src/video_core/rasterizer_cache/texture_cube.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/hash.h"
|
||||
#include "video_core/rasterizer_cache/slot_id.h"
|
||||
#include "video_core/regs_texturing.h"
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
struct TextureCube {
|
||||
SurfaceId surface_id;
|
||||
std::array<SurfaceId, 6> face_ids;
|
||||
std::array<u64, 6> ticks;
|
||||
};
|
||||
|
||||
struct TextureCubeConfig {
|
||||
PAddr px;
|
||||
PAddr nx;
|
||||
PAddr py;
|
||||
PAddr ny;
|
||||
PAddr pz;
|
||||
PAddr nz;
|
||||
u32 width;
|
||||
u32 levels;
|
||||
Pica::TexturingRegs::TextureFormat format;
|
||||
|
||||
bool operator==(const TextureCubeConfig& rhs) const {
|
||||
return std::memcmp(this, &rhs, sizeof(TextureCubeConfig)) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const TextureCubeConfig& rhs) const {
|
||||
return std::memcmp(this, &rhs, sizeof(TextureCubeConfig)) != 0;
|
||||
}
|
||||
|
||||
const u64 Hash() const {
|
||||
return Common::ComputeHash64(this, sizeof(TextureCubeConfig));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace VideoCore
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<VideoCore::TextureCubeConfig> {
|
||||
std::size_t operator()(const VideoCore::TextureCubeConfig& config) const noexcept {
|
||||
return config.Hash();
|
||||
}
|
||||
};
|
||||
} // namespace std
|
@@ -5,24 +5,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <span>
|
||||
#include "common/hash.h"
|
||||
#include "common/math_util.h"
|
||||
#include "common/slot_vector.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "video_core/regs_texturing.h"
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
using SurfaceId = Common::SlotId;
|
||||
using SamplerId = Common::SlotId;
|
||||
|
||||
/// Fake surface ID for null surfaces
|
||||
constexpr SurfaceId NULL_SURFACE_ID{0};
|
||||
/// Fake surface ID for null cube surfaces
|
||||
constexpr SurfaceId NULL_SURFACE_CUBE_ID{1};
|
||||
/// Fake sampler ID for null samplers
|
||||
constexpr SamplerId NULL_SAMPLER_ID{0};
|
||||
|
||||
struct Offset {
|
||||
u32 x = 0;
|
||||
u32 y = 0;
|
||||
@@ -79,30 +66,6 @@ struct StagingData {
|
||||
std::span<u8> mapped;
|
||||
};
|
||||
|
||||
struct TextureCubeConfig {
|
||||
PAddr px;
|
||||
PAddr nx;
|
||||
PAddr py;
|
||||
PAddr ny;
|
||||
PAddr pz;
|
||||
PAddr nz;
|
||||
u32 width;
|
||||
u32 levels;
|
||||
Pica::TexturingRegs::TextureFormat format;
|
||||
|
||||
bool operator==(const TextureCubeConfig& rhs) const {
|
||||
return std::memcmp(this, &rhs, sizeof(TextureCubeConfig)) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const TextureCubeConfig& rhs) const {
|
||||
return std::memcmp(this, &rhs, sizeof(TextureCubeConfig)) != 0;
|
||||
}
|
||||
|
||||
const u64 Hash() const {
|
||||
return Common::ComputeHash64(this, sizeof(TextureCubeConfig));
|
||||
}
|
||||
};
|
||||
|
||||
class SurfaceParams;
|
||||
|
||||
u32 MipLevels(u32 width, u32 height, u32 max_level);
|
||||
@@ -134,12 +97,3 @@ void DecodeTexture(const SurfaceParams& surface_info, PAddr start_addr, PAddr en
|
||||
std::span<u8> source, std::span<u8> dest, bool convert = false);
|
||||
|
||||
} // namespace VideoCore
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<VideoCore::TextureCubeConfig> {
|
||||
std::size_t operator()(const VideoCore::TextureCubeConfig& config) const noexcept {
|
||||
return config.Hash();
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
Reference in New Issue
Block a user