Fixed a bug with readback_resolve and readback_memexport that was responsible for a large portion of their overhead. readback_memexport and resolve are now usable for games, depending on your hardware. in my case games that were slideshows now run at like 20-30 fps, and my hardware isnt the best for xenia.
add split_map class for mapping keys to values in a way that optimizes for frequent searches and infrequent insertions/removals remove jump table implementation of GetColorRenderTargetFormatComponentCount, it was appearing relatively high in profiles. instead pack the component counts into a single 32 bit word, which is indexed by shifting Add cvar to align all basic blocks to a boundary Add mmio aware load paths liberally apply XE_RESTRICT in ringbuffer related code Removed the IS_TRUE and IS_FALSE opcodes, they were pointless duplicates of COMPARE_EQ/COMPARE_NE and i want to simplify our set of opcodes for future backends More work on LVSR/LVSL/STVR/STVL opcodes Optimized X64 translated code emission, now only compute instrkey once Add code for pre-computing integer division magic numbers Optimized GetHostViewportInfo a little Move args for GetHostViewportInfo into a class, cache the result and compare for future queries. moved GetHostViewportInfo far lower on the profile Add (currently not functional, and very racy) asynchronous memcpy code. will improve it and actually use it in future commits. Add non-temporal memcpy function for huge page-aligned allocations. Used for copying to shared memory/readback hoist are_accumulated_render_targets_valid_ check out of loop in render_target_cache already bound check. Add stosb/movsb code for small constant memcpys/memsets that arent worth the overhead of memcpy/memset
This commit is contained in:
@@ -43,23 +43,23 @@ enum KeyType {
|
||||
KEY_TYPE_V_F64 = OPCODE_SIG_TYPE_V + FLOAT64_TYPE,
|
||||
KEY_TYPE_V_V128 = OPCODE_SIG_TYPE_V + VEC128_TYPE,
|
||||
};
|
||||
|
||||
using InstrKeyValue = uint32_t;
|
||||
#pragma pack(push, 1)
|
||||
union InstrKey {
|
||||
uint32_t value;
|
||||
InstrKeyValue value;
|
||||
struct {
|
||||
uint32_t opcode : 8;
|
||||
uint32_t dest : 5;
|
||||
uint32_t src1 : 5;
|
||||
uint32_t src2 : 5;
|
||||
uint32_t src3 : 5;
|
||||
uint32_t reserved : 4;
|
||||
InstrKeyValue opcode : 8;
|
||||
InstrKeyValue dest : 5;
|
||||
InstrKeyValue src1 : 5;
|
||||
InstrKeyValue src2 : 5;
|
||||
InstrKeyValue src3 : 5;
|
||||
InstrKeyValue reserved : 4;
|
||||
};
|
||||
|
||||
operator uint32_t() const { return value; }
|
||||
operator InstrKeyValue() const { return value; }
|
||||
|
||||
InstrKey() : value(0) { static_assert_size(*this, sizeof(value)); }
|
||||
InstrKey(uint32_t v) : value(v) {}
|
||||
InstrKey(InstrKeyValue v) : value(v) {}
|
||||
|
||||
// this used to take about 1% cpu while precompiling
|
||||
// it kept reloading opcode, and also constantly repacking and unpacking the
|
||||
@@ -67,16 +67,16 @@ union InstrKey {
|
||||
InstrKey(const Instr* i) : value(0) {
|
||||
const OpcodeInfo* info = i->GetOpcodeInfo();
|
||||
|
||||
uint32_t sig = info->signature;
|
||||
InstrKeyValue sig = info->signature;
|
||||
|
||||
OpcodeSignatureType dest_type, src1_type, src2_type, src3_type;
|
||||
|
||||
UnpackOpcodeSig(sig, dest_type, src1_type, src2_type, src3_type);
|
||||
|
||||
uint32_t out_desttype = (uint32_t)dest_type;
|
||||
uint32_t out_src1type = (uint32_t)src1_type;
|
||||
uint32_t out_src2type = (uint32_t)src2_type;
|
||||
uint32_t out_src3type = (uint32_t)src3_type;
|
||||
InstrKeyValue out_desttype = (InstrKeyValue)dest_type;
|
||||
InstrKeyValue out_src1type = (InstrKeyValue)src1_type;
|
||||
InstrKeyValue out_src2type = (InstrKeyValue)src2_type;
|
||||
InstrKeyValue out_src3type = (InstrKeyValue)src3_type;
|
||||
|
||||
Value* destv = i->dest;
|
||||
// pre-deref, even if not value
|
||||
@@ -105,7 +105,7 @@ union InstrKey {
|
||||
template <Opcode OPCODE, KeyType DEST = KEY_TYPE_X, KeyType SRC1 = KEY_TYPE_X,
|
||||
KeyType SRC2 = KEY_TYPE_X, KeyType SRC3 = KEY_TYPE_X>
|
||||
struct Construct {
|
||||
static const uint32_t value =
|
||||
static const InstrKeyValue value =
|
||||
(OPCODE) | (DEST << 8) | (SRC1 << 13) | (SRC2 << 18) | (SRC3 << 23);
|
||||
};
|
||||
};
|
||||
@@ -307,8 +307,8 @@ struct I<OPCODE, DEST> : DestField<DEST> {
|
||||
protected:
|
||||
template <typename SEQ, typename T>
|
||||
friend struct Sequence;
|
||||
bool Load(const Instr* i) {
|
||||
if (InstrKey(i).value == key && BASE::LoadDest(i)) {
|
||||
bool Load(const Instr* i, InstrKeyValue kv) {
|
||||
if (kv == key && BASE::LoadDest(i)) {
|
||||
instr = i;
|
||||
return true;
|
||||
}
|
||||
@@ -329,8 +329,8 @@ struct I<OPCODE, DEST, SRC1> : DestField<DEST> {
|
||||
protected:
|
||||
template <typename SEQ, typename T>
|
||||
friend struct Sequence;
|
||||
bool Load(const Instr* i) {
|
||||
if (InstrKey(i).value == key && BASE::LoadDest(i)) {
|
||||
bool Load(const Instr* i, InstrKeyValue kv) {
|
||||
if (kv == key && BASE::LoadDest(i)) {
|
||||
instr = i;
|
||||
src1.Load(i->src1);
|
||||
return true;
|
||||
@@ -355,8 +355,8 @@ struct I<OPCODE, DEST, SRC1, SRC2> : DestField<DEST> {
|
||||
protected:
|
||||
template <typename SEQ, typename T>
|
||||
friend struct Sequence;
|
||||
bool Load(const Instr* i) {
|
||||
if (InstrKey(i).value == key && BASE::LoadDest(i)) {
|
||||
bool Load(const Instr* i, InstrKeyValue kv) {
|
||||
if (kv == key && BASE::LoadDest(i)) {
|
||||
instr = i;
|
||||
src1.Load(i->src1);
|
||||
src2.Load(i->src2);
|
||||
@@ -385,8 +385,8 @@ struct I<OPCODE, DEST, SRC1, SRC2, SRC3> : DestField<DEST> {
|
||||
protected:
|
||||
template <typename SEQ, typename T>
|
||||
friend struct Sequence;
|
||||
bool Load(const Instr* i) {
|
||||
if (InstrKey(i).value == key && BASE::LoadDest(i)) {
|
||||
bool Load(const Instr* i, InstrKeyValue ikey) {
|
||||
if (ikey == key && BASE::LoadDest(i)) {
|
||||
instr = i;
|
||||
src1.Load(i->src1);
|
||||
src2.Load(i->src2);
|
||||
@@ -422,9 +422,9 @@ struct Sequence {
|
||||
|
||||
static constexpr uint32_t head_key() { return T::key; }
|
||||
|
||||
static bool Select(X64Emitter& e, const Instr* i) {
|
||||
static bool Select(X64Emitter& e, const Instr* i, InstrKeyValue ikey) {
|
||||
T args;
|
||||
if (!args.Load(i)) {
|
||||
if (!args.Load(i, ikey)) {
|
||||
return false;
|
||||
}
|
||||
SEQ::Emit(e, args);
|
||||
|
||||
Reference in New Issue
Block a user