mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-26 07:39:56 -06:00
Merge vram dirty tracking
Squashed commit of the following: commit b463a05d4b909372f0cd1ad91caa0c77a25e5901 Author: RSDuck <rsduck@users.noreply.github.com> Date: Mon Nov 30 01:55:35 2020 +0100 minor fix commit ce73cebbdf5da243d7ebade82d8799ded9cd6b28 Author: RSDuck <rsduck@users.noreply.github.com> Date: Mon Nov 30 00:43:08 2020 +0100 fix dirty flags of BG/OBJ mappings not being reset commit fc5d73a6178e3adc444398bdd23de8314b5ca8f8 Author: RSDuck <rsduck@users.noreply.github.com> Date: Mon Nov 30 00:11:13 2020 +0100 use flat vram for gpu2d everywhere commit 34ee9fe2bf04fcfa2a5a1c8d78d70007e606f1a2 Author: RSDuck <rsduck@users.noreply.github.com> Date: Sat Nov 28 19:10:34 2020 +0100 mark VRAM dirty for display capture commit e8778fa2f429c6df0eece19d6a5ee83ae23a0cf4 Author: RSDuck <rsduck@users.noreply.github.com> Date: Sat Nov 28 18:59:31 2020 +0100 use flat VRAM for textures and texpals also skip rendering if nothing changed and a bunch of fixes commit 53f2041e2e1a28b35702a2ed51de885c36689f71 Author: RSDuck <rsduck@users.noreply.github.com> Date: Fri Nov 27 18:29:56 2020 +0100 use vram dirty tracking for extpals also preparations to take this further commit 4cdfa329e95aed26d3b21319c8fd86a04abf20f7 Author: RSDuck <rsduck@users.noreply.github.com> Date: Mon Nov 16 23:32:22 2020 +0100 VRAM dirty tracking
This commit is contained in:
149
src/NonStupidBitfield.h
Normal file
149
src/NonStupidBitfield.h
Normal file
@ -0,0 +1,149 @@
|
||||
#ifndef NONSTUPIDBITFIELD_H
|
||||
#define NONSTUPIDBITFIELD_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <algorithm>
|
||||
|
||||
// like std::bitset but less stupid and optimised for
|
||||
// our use case (keeping track of memory invalidations)
|
||||
|
||||
template <u32 Size>
|
||||
struct NonStupidBitField
|
||||
{
|
||||
static_assert((Size % 8) == 0, "bitfield size must be a multiple of 8");
|
||||
static const u32 DataLength = Size / 8;
|
||||
u8 Data[DataLength];
|
||||
|
||||
struct Ref
|
||||
{
|
||||
NonStupidBitField<Size>& BitField;
|
||||
u32 Idx;
|
||||
|
||||
operator bool()
|
||||
{
|
||||
return BitField.Data[Idx >> 3] & (1 << (Idx & 0x7));
|
||||
}
|
||||
|
||||
Ref& operator=(bool set)
|
||||
{
|
||||
BitField.Data[Idx >> 3] &= ~(1 << (Idx & 0x7));
|
||||
BitField.Data[Idx >> 3] |= ((u8)set << (Idx & 0x7));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct Iterator
|
||||
{
|
||||
NonStupidBitField<Size>& BitField;
|
||||
u32 DataIdx;
|
||||
u32 BitIdx;
|
||||
u64 RemainingBits;
|
||||
|
||||
u32 operator*() { return DataIdx * 8 + BitIdx; }
|
||||
|
||||
bool operator==(const Iterator& other) { return other.DataIdx == DataIdx; }
|
||||
bool operator!=(const Iterator& other) { return other.DataIdx != DataIdx; }
|
||||
|
||||
template <typename T>
|
||||
void Next()
|
||||
{
|
||||
while (RemainingBits == 0 && DataIdx < DataLength)
|
||||
{
|
||||
DataIdx += sizeof(T);
|
||||
RemainingBits = *(T*)&BitField.Data[DataIdx];
|
||||
}
|
||||
|
||||
BitIdx = __builtin_ctzll(RemainingBits);
|
||||
RemainingBits &= ~(1ULL << BitIdx);
|
||||
}
|
||||
|
||||
Iterator operator++(int)
|
||||
{
|
||||
Iterator prev(*this);
|
||||
++*this;
|
||||
return prev;
|
||||
}
|
||||
|
||||
Iterator& operator++()
|
||||
{
|
||||
if ((DataLength % 8) == 0)
|
||||
Next<u64>();
|
||||
else if ((DataLength % 4) == 0)
|
||||
Next<u32>();
|
||||
else if ((DataLength % 2) == 0)
|
||||
Next<u16>();
|
||||
else
|
||||
Next<u8>();
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
NonStupidBitField(u32 start, u32 size)
|
||||
{
|
||||
memset(Data, 0, sizeof(Data));
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
u32 roundedStartBit = (start + 7) & ~7;
|
||||
u32 roundedEndBit = (start + size) & ~7;
|
||||
if (roundedStartBit != roundedEndBit)
|
||||
memset(Data + roundedStartBit / 8, 0xFF, (roundedEndBit - roundedStartBit) / 8);
|
||||
|
||||
if (start & 0x7)
|
||||
Data[start >> 3] = 0xFF << (start & 0x7);
|
||||
if ((start + size) & 0x7)
|
||||
Data[(start + size) >> 3] = 0xFF >> ((start + size) & 0x7);
|
||||
}
|
||||
|
||||
NonStupidBitField()
|
||||
{
|
||||
memset(Data, 0, sizeof(Data));
|
||||
}
|
||||
|
||||
Iterator End()
|
||||
{
|
||||
return Iterator{*this, DataLength, 0, 0};
|
||||
}
|
||||
Iterator Begin()
|
||||
{
|
||||
if ((DataLength % 8) == 0)
|
||||
return ++Iterator{*this, 0, 0, *(u64*)Data};
|
||||
else if ((DataLength % 4) == 0)
|
||||
return ++Iterator{*this, 0, 0, *(u32*)Data};
|
||||
else if ((DataLength % 2) == 0)
|
||||
return ++Iterator{*this, 0, 0, *(u16*)Data};
|
||||
else
|
||||
return ++Iterator{*this, 0, 0, *Data};
|
||||
}
|
||||
|
||||
Ref operator[](u32 idx)
|
||||
{
|
||||
return Ref{*this, idx};
|
||||
}
|
||||
|
||||
NonStupidBitField& operator|=(const NonStupidBitField<Size>& other)
|
||||
{
|
||||
for (u32 i = 0; i < DataLength; i++)
|
||||
{
|
||||
Data[i] |= other.Data[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
NonStupidBitField& operator&=(const NonStupidBitField<Size>& other)
|
||||
{
|
||||
for (u32 i = 0; i < DataLength; i++)
|
||||
{
|
||||
Data[i] &= other.Data[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user