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:
@@ -59,16 +59,8 @@ class RingBuffer {
|
||||
// subtract instead
|
||||
void set_read_offset(size_t offset) { read_offset_ = offset % capacity_; }
|
||||
ring_size_t read_count() const {
|
||||
// chrispy: these branches are unpredictable
|
||||
#if 0
|
||||
if (read_offset_ == write_offset_) {
|
||||
return 0;
|
||||
} else if (read_offset_ < write_offset_) {
|
||||
return write_offset_ - read_offset_;
|
||||
} else {
|
||||
return (capacity_ - read_offset_) + write_offset_;
|
||||
}
|
||||
#else
|
||||
// chrispy: these branches are unpredictable
|
||||
|
||||
ring_size_t read_offs = read_offset_;
|
||||
ring_size_t write_offs = write_offset_;
|
||||
ring_size_t cap = capacity_;
|
||||
@@ -77,14 +69,6 @@ class RingBuffer {
|
||||
ring_size_t wrap_read_count = (cap - read_offs) + write_offs;
|
||||
|
||||
ring_size_t comparison_value = read_offs <= write_offs;
|
||||
#if 0
|
||||
size_t selector =
|
||||
static_cast<size_t>(-static_cast<ptrdiff_t>(comparison_value));
|
||||
offset_delta &= selector;
|
||||
|
||||
wrap_read_count &= ~selector;
|
||||
return offset_delta | wrap_read_count;
|
||||
#else
|
||||
|
||||
if (XE_LIKELY(read_offs <= write_offs)) {
|
||||
return offset_delta; // will be 0 if they are equal, semantically
|
||||
@@ -93,8 +77,6 @@ class RingBuffer {
|
||||
} else {
|
||||
return wrap_read_count;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
ring_size_t write_offset() const { return write_offset_; }
|
||||
@@ -116,9 +98,9 @@ class RingBuffer {
|
||||
void AdvanceWrite(size_t count);
|
||||
|
||||
struct ReadRange {
|
||||
const uint8_t* first;
|
||||
const uint8_t* XE_RESTRICT first;
|
||||
|
||||
const uint8_t* second;
|
||||
const uint8_t* XE_RESTRICT second;
|
||||
ring_size_t first_length;
|
||||
ring_size_t second_length;
|
||||
};
|
||||
@@ -126,9 +108,11 @@ class RingBuffer {
|
||||
void EndRead(ReadRange read_range);
|
||||
|
||||
/*
|
||||
BeginRead, but if there is a second Range it will prefetch all lines of it
|
||||
BeginRead, but if there is a second Range it will prefetch all lines of
|
||||
it
|
||||
|
||||
this does not prefetch the first range, because software prefetching can do that faster than we can
|
||||
this does not prefetch the first range, because software
|
||||
prefetching can do that faster than we can
|
||||
*/
|
||||
template <swcache::PrefetchTag tag>
|
||||
XE_FORCEINLINE ReadRange BeginPrefetchedRead(size_t count) {
|
||||
@@ -138,7 +122,7 @@ class RingBuffer {
|
||||
ring_size_t numlines =
|
||||
xe::align<ring_size_t>(range.second_length, XE_HOST_CACHE_LINE_SIZE) /
|
||||
XE_HOST_CACHE_LINE_SIZE;
|
||||
//chrispy: maybe unroll?
|
||||
// chrispy: maybe unroll?
|
||||
for (ring_size_t i = 0; i < numlines; ++i) {
|
||||
swcache::Prefetch<tag>(range.second + (i * XE_HOST_CACHE_LINE_SIZE));
|
||||
}
|
||||
@@ -187,7 +171,7 @@ class RingBuffer {
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t* buffer_ = nullptr;
|
||||
uint8_t* XE_RESTRICT buffer_ = nullptr;
|
||||
ring_size_t capacity_ = 0;
|
||||
ring_size_t read_offset_ = 0;
|
||||
ring_size_t write_offset_ = 0;
|
||||
|
||||
Reference in New Issue
Block a user