mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-10-20 18:59:26 +02:00
Experiment on descriptors payloads
This commit is contained in:
parent
98ad2d5e4c
commit
108c991431
7 changed files with 47 additions and 62 deletions
|
|
@ -33,7 +33,7 @@ using TextureInstVector = boost::container::small_vector<TextureInst, 24>;
|
||||||
|
|
||||||
constexpr u32 DESCRIPTOR_SIZE = 8;
|
constexpr u32 DESCRIPTOR_SIZE = 8;
|
||||||
constexpr u32 DESCRIPTOR_SIZE_SHIFT = u32(std::countr_zero(DESCRIPTOR_SIZE));
|
constexpr u32 DESCRIPTOR_SIZE_SHIFT = u32(std::countr_zero(DESCRIPTOR_SIZE));
|
||||||
constexpr u32 DESCRIPTOR_MAX_COUNT = 512;
|
constexpr u32 DESCRIPTOR_MAX_COUNT = 128;
|
||||||
constexpr u32 DESCRIPTOR_CBUF_BYTES = 16 * 1024;
|
constexpr u32 DESCRIPTOR_CBUF_BYTES = 16 * 1024;
|
||||||
|
|
||||||
u32 DynamicDescriptorSizeShift(const IR::U32& dynamic_offset) {
|
u32 DynamicDescriptorSizeShift(const IR::U32& dynamic_offset) {
|
||||||
|
|
|
||||||
|
|
@ -364,7 +364,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureCacheParams {
|
struct TextureCacheParams {
|
||||||
static constexpr bool ENABLE_VALIDATION = true;
|
|
||||||
static constexpr bool FRAMEBUFFER_BLITS = true;
|
static constexpr bool FRAMEBUFFER_BLITS = true;
|
||||||
static constexpr bool HAS_EMULATED_COPIES = true;
|
static constexpr bool HAS_EMULATED_COPIES = true;
|
||||||
static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
|
static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@ class Device;
|
||||||
class Scheduler;
|
class Scheduler;
|
||||||
|
|
||||||
class DescriptorBufferRing final {
|
class DescriptorBufferRing final {
|
||||||
static constexpr size_t FRAMES_IN_FLIGHT = 8;
|
static constexpr size_t FRAMES_IN_FLIGHT = 3;
|
||||||
static constexpr VkDeviceSize TILER_FRAME_SIZE = 2 * 1024 * 1024;
|
static constexpr VkDeviceSize TILER_FRAME_SIZE = 5 * 1024 * 1024;
|
||||||
static constexpr VkDeviceSize DESKTOP_FRAME_SIZE = 4 * 1024 * 1024;
|
static constexpr VkDeviceSize DESKTOP_FRAME_SIZE = 8 * 1024 * 1024;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DescriptorBufferRing(const Device& device_, MemoryAllocator& memory_allocator);
|
explicit DescriptorBufferRing(const Device& device_, MemoryAllocator& memory_allocator);
|
||||||
|
|
|
||||||
|
|
@ -552,7 +552,6 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureCacheParams {
|
struct TextureCacheParams {
|
||||||
static constexpr bool ENABLE_VALIDATION = true;
|
|
||||||
static constexpr bool FRAMEBUFFER_BLITS = false;
|
static constexpr bool FRAMEBUFFER_BLITS = false;
|
||||||
static constexpr bool HAS_EMULATED_COPIES = false;
|
static constexpr bool HAS_EMULATED_COPIES = false;
|
||||||
static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
|
static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <bit>
|
||||||
|
#include <cstring>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/div_ceil.h"
|
#include "common/div_ceil.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/slot_vector.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
|
|
||||||
|
|
@ -21,6 +25,12 @@ namespace VideoCommon {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class DescriptorTable {
|
class DescriptorTable {
|
||||||
public:
|
public:
|
||||||
|
struct Entry {
|
||||||
|
T descriptor;
|
||||||
|
Common::SlotId id;
|
||||||
|
u32 generation;
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] bool Synchronize(GPUVAddr gpu_addr, u32 limit) noexcept {
|
[[nodiscard]] bool Synchronize(GPUVAddr gpu_addr, u32 limit) noexcept {
|
||||||
bool ret = !(current_gpu_addr == gpu_addr && current_limit == limit);
|
bool ret = !(current_gpu_addr == gpu_addr && current_limit == limit);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
@ -30,44 +40,42 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void Invalidate() noexcept {
|
void Invalidate() noexcept {
|
||||||
std::ranges::fill(read_descriptors, 0);
|
++generation;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::pair<T, bool> Read(Tegra::MemoryManager const& gpu_memory, u32 index) noexcept {
|
[[nodiscard]] std::pair<Entry&, bool> Read(Tegra::MemoryManager const& gpu_memory, u32 index) noexcept {
|
||||||
DEBUG_ASSERT(index <= current_limit);
|
DEBUG_ASSERT(index <= current_limit);
|
||||||
const GPUVAddr gpu_addr = current_gpu_addr + index * sizeof(T);
|
const GPUVAddr gpu_addr = current_gpu_addr + index * sizeof(T);
|
||||||
std::pair<T, bool> result;
|
T value{};
|
||||||
gpu_memory.ReadBlockUnsafe(gpu_addr, std::addressof(result.first), sizeof(T));
|
if (!aligned) {
|
||||||
if ((read_descriptors[index / 64] & (1ULL << (index % 64))) != 0) {
|
gpu_memory.ReadBlockUnsafe(gpu_addr, std::addressof(value), sizeof(T));
|
||||||
result.second = result.first != descriptors[index];
|
} else if (const u8* const ptr = gpu_memory.GetPointer(gpu_addr)) {
|
||||||
} else {
|
std::memcpy(std::addressof(value), ptr, sizeof(T));
|
||||||
read_descriptors[index / 64] |= 1ULL << (index % 64);
|
|
||||||
result.second = true;
|
|
||||||
}
|
}
|
||||||
if (result.second) {
|
Entry& entry = entries[index];
|
||||||
descriptors[index] = result.first;
|
const bool is_new = entry.generation != generation || entry.descriptor != value;
|
||||||
|
if (is_new) {
|
||||||
|
entry.descriptor = value;
|
||||||
|
entry.generation = generation;
|
||||||
}
|
}
|
||||||
return result;
|
return {entry, is_new};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Refresh(GPUVAddr gpu_addr, u32 limit) noexcept {
|
void Refresh(GPUVAddr gpu_addr, u32 limit) noexcept {
|
||||||
current_gpu_addr = gpu_addr;
|
current_gpu_addr = gpu_addr;
|
||||||
current_limit = limit;
|
current_limit = limit;
|
||||||
// Mario Brothership reallocates a lot of times, so use aggressive pre-alloc sizes
|
aligned = gpu_addr % sizeof(T) == 0;
|
||||||
// std::vector<T> by default uses quadratic growth, but that isn't even enough to satisfy brothership
|
++generation;
|
||||||
const size_t num_descriptors = ((limit + 0x80000) & (~0x7ffff)) + 1;
|
if (entries.size() <= limit) {
|
||||||
size_t old_size = read_descriptors.size();
|
entries.resize(std::bit_ceil(size_t{limit} + 1));
|
||||||
read_descriptors.resize(Common::DivCeil(num_descriptors, 64U));
|
}
|
||||||
old_size = (std::min)(old_size, read_descriptors.size());
|
|
||||||
std::fill(read_descriptors.begin(), read_descriptors.begin() + old_size, 0);
|
|
||||||
//
|
|
||||||
descriptors.resize(num_descriptors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u64> read_descriptors;
|
std::vector<Entry> entries;
|
||||||
std::vector<T> descriptors;
|
|
||||||
GPUVAddr current_gpu_addr{};
|
GPUVAddr current_gpu_addr{};
|
||||||
u32 current_limit{};
|
u32 current_limit{};
|
||||||
|
u32 generation{1};
|
||||||
|
bool aligned{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
|
|
||||||
|
|
@ -270,14 +270,11 @@ SamplerId TextureCache<P>::GetSamplerId(u32 index, bool compute) {
|
||||||
LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index);
|
LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index);
|
||||||
return NULL_SAMPLER_ID;
|
return NULL_SAMPLER_ID;
|
||||||
}
|
}
|
||||||
auto const map_index = index | (compute ? Common::SlotId::TAGGED_VALUE : 0);
|
auto const [entry, is_new] = table.Read(*gpu_memory, index);
|
||||||
auto const [descriptor, is_new] = table.Read(*gpu_memory, index);
|
|
||||||
if (is_new) {
|
if (is_new) {
|
||||||
auto const id = FindSampler(descriptor, compute);
|
entry.id = FindSampler(entry.descriptor, compute);
|
||||||
channel_state->sampler_ids.insert_or_assign(map_index, id);
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
return channel_state->sampler_ids.find(map_index)->second;
|
return entry.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
|
|
@ -500,26 +497,19 @@ ImageViewId TextureCache<P>::VisitImageView(u32 index, bool compute) {
|
||||||
LOG_DEBUG(HW_GPU, "Invalid image view index={}", index);
|
LOG_DEBUG(HW_GPU, "Invalid image view index={}", index);
|
||||||
return NULL_IMAGE_VIEW_ID;
|
return NULL_IMAGE_VIEW_ID;
|
||||||
}
|
}
|
||||||
auto const map_index = index | (compute ? Common::SlotId::TAGGED_VALUE : 0);
|
auto const [entry, is_new] = table.Read(*gpu_memory, index);
|
||||||
// Is new (on the tegra engine side)?
|
|
||||||
auto const [descriptor, is_new] = table.Read(*gpu_memory, index);
|
|
||||||
if (is_new) {
|
if (is_new) {
|
||||||
if (IsValidEntry(*gpu_memory, descriptor)) {
|
entry.id = NULL_IMAGE_VIEW_ID;
|
||||||
// Is new (registered view) on the texture cache side?
|
if (IsValidEntry(*gpu_memory, entry.descriptor)) {
|
||||||
const auto [pair, is_new_tc] = channel_state->image_views.try_emplace(descriptor);
|
const auto [pair, is_new_tc] = channel_state->image_views.try_emplace(entry.descriptor);
|
||||||
if (is_new_tc)
|
if (is_new_tc)
|
||||||
pair->second = CreateImageView(descriptor);
|
pair->second = CreateImageView(entry.descriptor);
|
||||||
PrepareImageView(pair->second, false, false);
|
entry.id = pair->second;
|
||||||
channel_state->image_view_ids.insert_or_assign(map_index, pair->second);
|
|
||||||
return pair->second;
|
|
||||||
}
|
}
|
||||||
channel_state->image_view_ids.insert_or_assign(map_index, NULL_IMAGE_VIEW_ID);
|
|
||||||
return NULL_IMAGE_VIEW_ID;
|
|
||||||
}
|
}
|
||||||
auto const it = channel_state->image_view_ids.find(map_index);
|
if (entry.id != NULL_IMAGE_VIEW_ID)
|
||||||
if (it->second != NULL_IMAGE_VIEW_ID)
|
PrepareImageView(entry.id, false, false);
|
||||||
PrepareImageView(it->second, false, false);
|
return entry.id;
|
||||||
return it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
|
|
@ -1296,9 +1286,6 @@ void TextureCache<P>::InvalidateScale(Image& image) {
|
||||||
for (size_t c : active_channel_ids) {
|
for (size_t c : active_channel_ids) {
|
||||||
auto& channel_info = channel_storage[c];
|
auto& channel_info = channel_storage[c];
|
||||||
|
|
||||||
if constexpr (ENABLE_VALIDATION)
|
|
||||||
for (auto& e : channel_info.image_view_ids)
|
|
||||||
e.second = CORRUPT_ID;
|
|
||||||
channel_info.graphics_image_table.Invalidate();
|
channel_info.graphics_image_table.Invalidate();
|
||||||
channel_info.compute_image_table.Invalidate();
|
channel_info.compute_image_table.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
@ -2295,9 +2282,6 @@ void TextureCache<P>::DeleteImage(ImageId image_id, bool immediate_delete) {
|
||||||
}
|
}
|
||||||
for (size_t c : active_channel_ids) {
|
for (size_t c : active_channel_ids) {
|
||||||
auto& channel_info = channel_storage[c];
|
auto& channel_info = channel_storage[c];
|
||||||
if constexpr (ENABLE_VALIDATION)
|
|
||||||
for (auto& e : channel_info.image_view_ids)
|
|
||||||
e.second = CORRUPT_ID;
|
|
||||||
channel_info.graphics_image_table.Invalidate();
|
channel_info.graphics_image_table.Invalidate();
|
||||||
channel_info.compute_image_table.Invalidate();
|
channel_info.compute_image_table.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,9 +89,6 @@ public:
|
||||||
std::unordered_map<TICEntry, ImageViewId> image_views;
|
std::unordered_map<TICEntry, ImageViewId> image_views;
|
||||||
std::unordered_map<TSCEntry, SamplerId> samplers;
|
std::unordered_map<TSCEntry, SamplerId> samplers;
|
||||||
|
|
||||||
::Common::unordered_map<u32, SamplerId> sampler_ids;
|
|
||||||
::Common::unordered_map<u32, ImageViewId> image_view_ids;
|
|
||||||
|
|
||||||
TextureCacheGPUMap* gpu_page_table = nullptr;
|
TextureCacheGPUMap* gpu_page_table = nullptr;
|
||||||
TextureCacheGPUMap* sparse_page_table = nullptr;
|
TextureCacheGPUMap* sparse_page_table = nullptr;
|
||||||
};
|
};
|
||||||
|
|
@ -101,8 +98,6 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI
|
||||||
/// Address shift for caching images into a hash table
|
/// Address shift for caching images into a hash table
|
||||||
static constexpr u64 YUZU_PAGEBITS = 20;
|
static constexpr u64 YUZU_PAGEBITS = 20;
|
||||||
|
|
||||||
/// Enables debugging features to the texture cache
|
|
||||||
static constexpr bool ENABLE_VALIDATION = P::ENABLE_VALIDATION;
|
|
||||||
/// Implement blits as copies between framebuffers
|
/// Implement blits as copies between framebuffers
|
||||||
static constexpr bool FRAMEBUFFER_BLITS = P::FRAMEBUFFER_BLITS;
|
static constexpr bool FRAMEBUFFER_BLITS = P::FRAMEBUFFER_BLITS;
|
||||||
/// True when some copies have to be emulated
|
/// True when some copies have to be emulated
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue