Compare commits

..

4 Commits

Author SHA1 Message Date
lizzie 8bccdabf99 [common] reuse base mapping on POSIX on MultiLevelPageTable
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-04-04 21:01:09 +02:00
lizzie ac99ea96da [dynarmic] fix bayonetta 3 regression due to LUT in #3718 (#3822)
minor oversight

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3822
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-04-03 17:33:44 +02:00
lizzie d1b7824443 [meta] Restore base icon (#3809)
Merge AFTER april fools
Signed-off-by: lizzie lizzie@eden-emu.dev

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3809
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-04-02 06:06:46 +02:00
wildcard 34fa39eae8 [texture_cache] Skip alias synchronization in texture cache when the image has no aliases. (#3740)
PrepareImage() is on a very hot path and previously called SynchronizeAliases() unconditionally.  For most images, aliased_images` is empty, so this created unnecessary overhead, now we only synchronize only when image requires it

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3740
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: wildcard <wildcard@eden-emu.dev>
Co-committed-by: wildcard <wildcard@eden-emu.dev>
2026-04-02 06:06:16 +02:00
19 changed files with 327 additions and 160 deletions
+212 -71
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 13 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 KiB

After

Width:  |  Height:  |  Size: 256 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

After

Width:  |  Height:  |  Size: 335 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 67 KiB

@@ -1 +1 @@
<?xml version='1.0' encoding='utf-8'?><resources><color name='ic_launcher_background'>#43fcfcff</color></resources>
<?xml version='1.0' encoding='utf-8'?><resources><color name='ic_launcher_background'>#1F143C</color></resources>
+10 -21
View File
@@ -30,12 +30,9 @@ MultiLevelPageTable<BaseAddr>::MultiLevelPageTable(std::size_t address_space_bit
void* base{VirtualAlloc(nullptr, alloc_size, MEM_RESERVE, PAGE_READWRITE)};
#else
void* base{mmap(nullptr, alloc_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)};
if (base == MAP_FAILED) {
if (base == MAP_FAILED)
base = nullptr;
}
#endif
ASSERT(base);
base_ptr = reinterpret_cast<BaseAddr*>(base);
}
@@ -56,29 +53,21 @@ template <typename BaseAddr>
void MultiLevelPageTable<BaseAddr>::ReserveRange(u64 start, std::size_t size) {
const u64 new_start = start >> first_level_shift;
const u64 new_end = (start + size) >> first_level_shift;
for (u64 i = new_start; i <= new_end; i++) {
if (!first_level_map[i]) {
for (u64 i = new_start; i <= new_end; i++)
if (!first_level_map[i])
AllocateLevel(i);
}
}
}
template <typename BaseAddr>
void MultiLevelPageTable<BaseAddr>::AllocateLevel(u64 level) {
void* ptr = reinterpret_cast<char *>(base_ptr) + level * first_level_chunk_size;
void MultiLevelPageTable<BaseAddr>::AllocateLevel(u64 index) {
void* ptr = reinterpret_cast<char *>(base_ptr) + index * first_level_chunk_size;
#ifdef _WIN32
void* base{VirtualAlloc(ptr, first_level_chunk_size, MEM_COMMIT, PAGE_READWRITE)};
#else
void* base{mmap(ptr, first_level_chunk_size, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)};
if (base == MAP_FAILED) {
base = nullptr;
}
#endif
void* base = VirtualAlloc(ptr, first_level_chunk_size, MEM_COMMIT, PAGE_READWRITE);
ASSERT(base);
first_level_map[level] = base;
#else
void* base = ptr;
#endif
first_level_map[index] = base;
}
} // namespace Common
@@ -1985,6 +1985,13 @@ void EmitX64::EmitFPVectorToHalf32(EmitContext& ctx, IR::Inst* inst) {
// output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));
// }
template<size_t fsize, bool unsigned_, FP::RoundingMode rounding_mode, size_t fbits>
static void EmitFPVectorToFixedThunk(VectorArray<mcl::unsigned_integer_of_size<fsize>>& output, const VectorArray<mcl::unsigned_integer_of_size<fsize>>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
using FPT = mcl::unsigned_integer_of_size<fsize>;
for (size_t i = 0; i < output.size(); ++i)
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));
}
template<size_t fsize, bool unsigned_>
void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
const size_t fbits = inst->GetArg(1).GetU8();
@@ -2106,43 +2113,88 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(code, inst, src);
return;
}
auto const fpt_fn = [fbits, rounding]() -> void (*)(VectorArray<mcl::unsigned_integer_of_size<fsize>>& output, const VectorArray<mcl::unsigned_integer_of_size<fsize>>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
#define ROUNDING_MODE_CASE(CASE, N) \
if (rounding == FP::RoundingMode::CASE && fsize >= (N) && fbits == (N)) return &EmitFPVectorToFixedThunk<fsize, unsigned_, FP::RoundingMode::CASE, N>;
#define ROUNDING_MODE_SWITCH(CASE) \
ROUNDING_MODE_CASE(CASE, 0x00) \
ROUNDING_MODE_CASE(CASE, 0x01) \
ROUNDING_MODE_CASE(CASE, 0x02) \
ROUNDING_MODE_CASE(CASE, 0x03) \
ROUNDING_MODE_CASE(CASE, 0x04) \
ROUNDING_MODE_CASE(CASE, 0x05) \
ROUNDING_MODE_CASE(CASE, 0x06) \
ROUNDING_MODE_CASE(CASE, 0x07) \
ROUNDING_MODE_CASE(CASE, 0x08) \
ROUNDING_MODE_CASE(CASE, 0x09) \
ROUNDING_MODE_CASE(CASE, 0x0a) \
ROUNDING_MODE_CASE(CASE, 0x0b) \
ROUNDING_MODE_CASE(CASE, 0x0c) \
ROUNDING_MODE_CASE(CASE, 0x0d) \
ROUNDING_MODE_CASE(CASE, 0x0e) \
ROUNDING_MODE_CASE(CASE, 0x0f) \
ROUNDING_MODE_CASE(CASE, 0x10) \
ROUNDING_MODE_CASE(CASE, 0x11) \
ROUNDING_MODE_CASE(CASE, 0x12) \
ROUNDING_MODE_CASE(CASE, 0x13) \
ROUNDING_MODE_CASE(CASE, 0x14) \
ROUNDING_MODE_CASE(CASE, 0x15) \
ROUNDING_MODE_CASE(CASE, 0x16) \
ROUNDING_MODE_CASE(CASE, 0x17) \
ROUNDING_MODE_CASE(CASE, 0x18) \
ROUNDING_MODE_CASE(CASE, 0x19) \
ROUNDING_MODE_CASE(CASE, 0x1a) \
ROUNDING_MODE_CASE(CASE, 0x1b) \
ROUNDING_MODE_CASE(CASE, 0x1c) \
ROUNDING_MODE_CASE(CASE, 0x1d) \
ROUNDING_MODE_CASE(CASE, 0x1e) \
ROUNDING_MODE_CASE(CASE, 0x1f) \
ROUNDING_MODE_CASE(CASE, 0x20) \
ROUNDING_MODE_CASE(CASE, 0x21) \
ROUNDING_MODE_CASE(CASE, 0x22) \
ROUNDING_MODE_CASE(CASE, 0x23) \
ROUNDING_MODE_CASE(CASE, 0x24) \
ROUNDING_MODE_CASE(CASE, 0x25) \
ROUNDING_MODE_CASE(CASE, 0x26) \
ROUNDING_MODE_CASE(CASE, 0x27) \
ROUNDING_MODE_CASE(CASE, 0x28) \
ROUNDING_MODE_CASE(CASE, 0x29) \
ROUNDING_MODE_CASE(CASE, 0x2a) \
ROUNDING_MODE_CASE(CASE, 0x2b) \
ROUNDING_MODE_CASE(CASE, 0x2c) \
ROUNDING_MODE_CASE(CASE, 0x2d) \
ROUNDING_MODE_CASE(CASE, 0x2e) \
ROUNDING_MODE_CASE(CASE, 0x2f) \
ROUNDING_MODE_CASE(CASE, 0x30) \
ROUNDING_MODE_CASE(CASE, 0x31) \
ROUNDING_MODE_CASE(CASE, 0x32) \
ROUNDING_MODE_CASE(CASE, 0x33) \
ROUNDING_MODE_CASE(CASE, 0x34) \
ROUNDING_MODE_CASE(CASE, 0x35) \
ROUNDING_MODE_CASE(CASE, 0x36) \
ROUNDING_MODE_CASE(CASE, 0x37) \
ROUNDING_MODE_CASE(CASE, 0x38) \
ROUNDING_MODE_CASE(CASE, 0x39) \
ROUNDING_MODE_CASE(CASE, 0x3a) \
ROUNDING_MODE_CASE(CASE, 0x3b) \
ROUNDING_MODE_CASE(CASE, 0x3c) \
ROUNDING_MODE_CASE(CASE, 0x3d) \
ROUNDING_MODE_CASE(CASE, 0x3e) \
ROUNDING_MODE_CASE(CASE, 0x3f)
using FPT = mcl::unsigned_integer_of_size<fsize>; // WORKAROUND: For issue 678 on MSVC
auto const func = [rounding]() -> void(*)(VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
switch (rounding) {
case FP::RoundingMode::ToNearest_TieEven:
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
for (size_t i = 0; i < output.size(); ++i)
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::ToNearest_TieEven, fpsr));
};
case FP::RoundingMode::TowardsPlusInfinity:
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
for (size_t i = 0; i < output.size(); ++i)
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::TowardsPlusInfinity, fpsr));
};
case FP::RoundingMode::TowardsMinusInfinity:
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
for (size_t i = 0; i < output.size(); ++i)
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::TowardsMinusInfinity, fpsr));
};
case FP::RoundingMode::TowardsZero:
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
for (size_t i = 0; i < output.size(); ++i)
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::TowardsZero, fpsr));
};
case FP::RoundingMode::ToNearest_TieAwayFromZero:
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
for (size_t i = 0; i < output.size(); ++i)
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::ToNearest_TieAwayFromZero, fpsr));
};
case FP::RoundingMode::ToOdd:
return [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
for (size_t i = 0; i < output.size(); ++i)
output[i] = FPT(FP::FPToFixed<FPT>(fsize, input[i], fsize, unsigned_, fpcr, FP::RoundingMode::ToOdd, fpsr));
};
}
// FUCK YOU MSVC, FUCKING DEPTH CANT EVEN HANDLE 8+16+32+64 DEPTH OF A ELSE STATMENT YOU FUCKING STUPID
// BURN MSVC BURN IT STUPID COMPILER CAN'T EVEN COMPILE THE MOST BASIC C++
ROUNDING_MODE_SWITCH(ToNearest_TieEven)
ROUNDING_MODE_SWITCH(TowardsPlusInfinity)
ROUNDING_MODE_SWITCH(TowardsMinusInfinity)
ROUNDING_MODE_SWITCH(TowardsZero)
ROUNDING_MODE_SWITCH(ToNearest_TieAwayFromZero)
#undef ROUNDING_MODE_SWITCH
#undef ROUNDING_MODE_CASE
return nullptr;
}();
EmitTwoOpFallback<3>(code, ctx, inst, func);
EmitTwoOpFallback<3>(code, ctx, inst, fpt_fn);
}
void EmitX64::EmitFPVectorToSignedFixed16(EmitContext& ctx, IR::Inst* inst) {
+3 -1
View File
@@ -2733,7 +2733,9 @@ void TextureCache<P>::PrepareImage(ImageId image_id, bool is_modification, bool
}
} else {
RefreshContents(image, image_id);
SynchronizeAliases(image_id);
if (!image.aliased_images.empty()) {
SynchronizeAliases(image_id);
}
}
if (is_modification) {
MarkModification(image);
+9 -25
View File
@@ -18,25 +18,8 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
// Padding, dimensions, alignment...
const int column = index.row() % m_columns;
const int cell_width = option.rect.width();
const int fixed_card_width = cell_width - m_padding;
const int margins = 8;
// The gist of it is that this anchors the left and right sides to the edges,
// while maintaining an even gap between each card.
// I just smashed random keys into my keyboard until something worked.
// Don't even bother trying to figure out what the hell this is doing.
const auto total_row_width = m_columns * cell_width;
const auto total_gap_space = total_row_width - (margins * 2) - (m_columns * fixed_card_width);
const auto gap = (m_columns > 1) ? (total_gap_space / (m_columns - 1)) : 0;
const auto relative_x = margins + (column * (fixed_card_width + gap));
const auto x_pos = option.rect.left() - (column * cell_width) + static_cast<int>(relative_x);
// also, add some additional padding here to prevent card overlap
QRect cardRect(x_pos + 4, option.rect.top() + 4, fixed_card_width - 8, option.rect.height() - margins);
// padding
QRect cardRect = option.rect.adjusted(4 + m_padding / 2, 4, -4 - m_padding / 2, -4);
// colors
QPalette palette = option.palette;
@@ -58,6 +41,8 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
painter->setPen(QPen(borderColor, 1));
painter->drawRoundedRect(cardRect, 10, 10);
static constexpr const int padding = 8;
// icon
int _iconsize = UISettings::values.game_icon_size.GetValue();
QSize iconSize(_iconsize, _iconsize);
@@ -69,7 +54,7 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
scaledSize.scale(iconSize, Qt::KeepAspectRatio);
int x = cardRect.left() + (cardRect.width() - scaledSize.width()) / 2;
int y = cardRect.top() + margins;
int y = cardRect.top() + padding;
iconRect = QRect(x, y, scaledSize.width(), scaledSize.height());
@@ -88,7 +73,7 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
painter->restore();
} else {
// if there is no icon just draw a blank rect
iconRect = QRect(cardRect.left() + margins, cardRect.top() + margins, _iconsize, _iconsize);
iconRect = QRect(cardRect.left() + padding, cardRect.top() + padding, _iconsize, _iconsize);
}
if (UISettings::values.show_game_name.GetValue()) {
@@ -97,8 +82,8 @@ void GameCard::paint(QPainter* painter, const QStyleOptionViewItem& option,
// padding + text
QRect textRect = cardRect;
textRect.setTop(iconRect.bottom() + margins);
textRect.adjust(margins, 0, -margins, -margins);
textRect.setTop(iconRect.bottom() + 8);
textRect.adjust(padding, 0, -padding, -padding);
// We are already crammed on space, ignore the row 2
QString title = index.data(Qt::DisplayRole).toString();
@@ -126,8 +111,7 @@ QSize GameCard::sizeHint(const QStyleOptionViewItem& option, const QModelIndex&
return m_size;
}
void GameCard::setSize(const QSize& newSize, const int padding, const int columns) {
void GameCard::setSize(const QSize& newSize, const int padding) {
m_size = newSize;
m_padding = padding;
m_columns = columns;
}
+1 -2
View File
@@ -18,10 +18,9 @@ public:
const QModelIndex& index) const override;
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void setSize(const QSize& newSize, const int padding, const int columns);
void setSize(const QSize& newSize, const int padding);
private:
QSize m_size;
int m_padding;
int m_columns;
};
+4 -4
View File
@@ -411,7 +411,7 @@ GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvid
list_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
list_view->setContextMenuPolicy(Qt::CustomContextMenu);
list_view->setGridSize(QSize(140, 160));
m_gameCard->setSize(list_view->gridSize(), 0, 4);
m_gameCard->setSize(list_view->gridSize(), 0);
list_view->setSpacing(10);
list_view->setWordWrap(true);
@@ -1051,8 +1051,8 @@ void GameList::UpdateIconSize() {
// And now stretch it a bit to fill out remaining space.
// Not perfect but works well enough for now
int columns = std::max(1, (view_width - 16) / min_item_width);
int stretched_width = ((view_width) - (spacing * (columns - 1))) / columns;
int columns = std::max(1, view_width / min_item_width);
int stretched_width = (view_width - (spacing * (columns - 1))) / columns;
// only updates things if grid size is changed
QSize grid_size(stretched_width, icon_size + heightMargin);
@@ -1060,7 +1060,7 @@ void GameList::UpdateIconSize() {
list_view->setUpdatesEnabled(false);
list_view->setGridSize(grid_size);
m_gameCard->setSize(grid_size, stretched_width - min_item_width, columns);
m_gameCard->setSize(grid_size, stretched_width - min_item_width);
list_view->setUpdatesEnabled(true);
}