mirror of
https://github.com/FelipePrado0/SpartanPort.git
synced 2026-11-07 10:45:59 -10:00
EN-US - Fixed texture cache image references moving when the cache grows, out-of-range slot IDs, per-dimension extent checks, view clamping, padding-only overlaps and in-flight sampler destruction - Fixed depth and colour buffer copies to copy every shared mip and layer - Fixed scheduler null chunks at 0x20000, exit 23 from oversized recording data and stale idle signals releasing new submissions - Fixed IRQ heap corruption at startup and saved packet sizes before running packets - Fixed shader cache loss: queued writes drained at exit, partial loads rejected, damaged records skipped - Fixed draws whose pipelines the driver refuses, speculative specialization exceptions and null user-data tables at area loads - Updated texture pressure to start at 60% of the budget on cards below 8 GB, unblocked evictions behind retained images and kept GPU-only images below the critical mark - Added tests for the slot vector, subresource extents, IRQ controller, record data, cache storage, cache flush, serdes and shader user data --- PT-BR - Corrigidos no cache de texturas: referências de imagem que mudavam de lugar quando o cache crescia, IDs de slot fora do intervalo, checagem de tamanho por dimensão, recorte de views, sobreposição só de padding e destruição de samplers em uso - Corrigidas as cópias de buffers de depth e color para copiar todos os mips e layers compartilhados - Corrigidos no scheduler: chunks nulos em 0x20000, exit 23 com dados de gravação grandes demais e sinais de ocioso antigos liberando submissões novas - Corrigida a corrupção do heap de IRQ na inicialização, e o tamanho dos pacotes passou a ser salvo antes de executá-los - Corrigida a perda do cache de shaders: gravações na fila esvaziadas ao sair, cargas parciais rejeitadas e registros danificados pulados - Corrigidos os draws com pipeline recusado pelo driver, as exceções de especialização especulativa e as tabelas de user data nulas na troca de área - Atualizada a pressão de texturas para começar em 60% do orçamento em placas com menos de 8 GB, desbloqueadas as remoções atrás de imagens retidas e mantidas as imagens só da GPU abaixo da marca crítica - Adicionados testes de slot vector, subresource extents, controlador de IRQ, record data, cache storage, flush do cache, serdes e shader user data
115 lines
4.1 KiB
C++
115 lines
4.1 KiB
C++
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
#include <array>
|
|
#include <cassert>
|
|
#include <cstdio>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
#include "common/slot_vector.h"
|
|
|
|
// This standalone test uses the production header and page operations, with a fatal
|
|
// assertion sink instead of the GPU logger. It needs no renderer or game resources.
|
|
void assert_fail_impl() {
|
|
std::abort();
|
|
}
|
|
namespace Common::Log {
|
|
bool ShouldLog(Level) {
|
|
return true;
|
|
}
|
|
void Write(std::string_view, Level, const char*, int, const char*, std::string&& message) {
|
|
std::fprintf(stderr, "%s\n", message.c_str());
|
|
}
|
|
} // namespace Common::Log
|
|
|
|
struct alignas(64) Item {
|
|
explicit Item(unsigned value_) : value(value_) {
|
|
++constructed;
|
|
++live;
|
|
payload.fill(value);
|
|
}
|
|
Item(const Item&) = delete;
|
|
Item(Item&&) = delete;
|
|
~Item() {
|
|
--live;
|
|
++destroyed;
|
|
}
|
|
unsigned value;
|
|
std::array<unsigned, 38> payload; // 192-byte entries straddle 2 MiB chunk boundaries.
|
|
static inline unsigned live = 0, constructed = 0, destroyed = 0;
|
|
};
|
|
|
|
int main() {
|
|
constexpr unsigned count = 50000;
|
|
static_assert(sizeof(Item) == 192);
|
|
static_assert(!std::is_copy_constructible_v<Common::SlotVector<Item>>);
|
|
static_assert(!std::is_move_constructible_v<Common::SlotVector<Item>>);
|
|
std::vector<Common::SlotId> ids;
|
|
std::vector<Item*> addresses;
|
|
ids.reserve(count);
|
|
addresses.reserve(count);
|
|
{
|
|
Common::SlotVector<Item> pool;
|
|
assert(pool.size() == 0);
|
|
assert(pool.begin() == pool.end());
|
|
// The first 2 MiB chunk rounds its allocation bitset up to a full word.
|
|
constexpr u32 initial_capacity = (2u << 20) / sizeof(Item);
|
|
constexpr u32 bitset_end = ((initial_capacity + 63) / 64) * 64;
|
|
assert(!pool.is_allocated(Common::SlotId{0}));
|
|
assert(!pool.is_allocated(Common::SlotId{63}));
|
|
assert(!pool.is_allocated(Common::SlotId{64}));
|
|
assert(!pool.is_allocated(Common::SlotId{bitset_end - 1}));
|
|
assert(!pool.is_allocated(Common::SlotId{bitset_end}));
|
|
assert(!pool.is_allocated(Common::SlotId{}));
|
|
assert(!pool.is_allocated(Common::SlotId{Common::SlotId::INVALID_INDEX - 1}));
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
ids.push_back(pool.insert(i));
|
|
assert(pool.is_allocated(ids.back()));
|
|
addresses.push_back(&pool[ids.back()]);
|
|
assert(reinterpret_cast<std::uintptr_t>(addresses.back()) % alignof(Item) == 0);
|
|
assert(&pool[ids.front()] == addresses.front());
|
|
}
|
|
assert(pool.size() == count);
|
|
assert(Item::live == count);
|
|
assert(!pool.is_allocated(Common::SlotId{}));
|
|
assert(!pool.is_allocated(Common::SlotId{Common::SlotId::INVALID_INDEX - 1}));
|
|
unsigned visited = 0;
|
|
for (auto& item : pool) {
|
|
assert(item.value == visited);
|
|
assert(&item == addresses[visited]);
|
|
for (auto value : item.payload) {
|
|
assert(value == visited);
|
|
}
|
|
++visited;
|
|
}
|
|
assert(visited == count);
|
|
for (unsigned i = 0; i < count; i += 2) {
|
|
pool.erase(ids[i]);
|
|
assert(!pool.is_allocated(ids[i]));
|
|
}
|
|
assert(pool.size() == count / 2);
|
|
visited = 0;
|
|
for (auto& item : pool) {
|
|
assert(item.value == visited * 2 + 1);
|
|
++visited;
|
|
}
|
|
assert(visited == count / 2);
|
|
for (unsigned i = 0; i < count / 2; ++i) {
|
|
const auto id = pool.insert(count + i);
|
|
assert(pool.is_allocated(id));
|
|
assert(id.index % 2 == 0);
|
|
assert(&pool[id] == addresses[id.index]);
|
|
}
|
|
for (unsigned i = 1; i < count; i += 2) {
|
|
assert(&pool[ids[i]] == addresses[i]);
|
|
assert(pool[ids[i]].value == i);
|
|
}
|
|
assert(pool.size() == count);
|
|
}
|
|
assert(Item::live == 0);
|
|
assert(Item::constructed == count + count / 2);
|
|
assert(Item::destroyed == Item::constructed);
|
|
std::puts("SlotVector: 50000 stable entries, alignment, iteration, reuse and destruction passed");
|
|
}
|