mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
129 lines
3.8 KiB
C++
129 lines
3.8 KiB
C++
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_IMAGE_H_
|
|
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_IMAGE_H_
|
|
|
|
#include "common/assert.h"
|
|
#include "graphics/host_gpu/renderer/imageInfo.h"
|
|
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
#include <span>
|
|
|
|
namespace Libs::Graphics {
|
|
|
|
struct Image final: ImageInfo {
|
|
Image& operator=(const ImageInfo& value) {
|
|
if (IsCpuDirty()) {
|
|
EXIT("dirty sampled image cannot be reassigned\n");
|
|
}
|
|
static_cast<ImageInfo&>(*this) = value;
|
|
m_track_begin = address;
|
|
m_track_end = address + size;
|
|
m_maybe_cpu_hash_valid = false;
|
|
return *this;
|
|
}
|
|
|
|
void InvalidateCpuWrite(uint64_t vaddr, uint64_t size) {
|
|
if (ImageRangeOverlaps(address, this->size, vaddr, size)) {
|
|
m_cpu_dirty = true;
|
|
m_maybe_cpu_dirty = false;
|
|
m_maybe_cpu_hash_valid = false;
|
|
m_track_begin = m_track_end;
|
|
} else if (ImagePageRangesOverlap(address, this->size, vaddr, size)) {
|
|
constexpr uint64_t page_mask = 4096 - 1;
|
|
if (vaddr + size <= address) {
|
|
const auto next_page = (address + page_mask) & ~page_mask;
|
|
m_track_begin = std::min(m_track_end, std::max(m_track_begin, next_page));
|
|
} else if (vaddr >= address + this->size) {
|
|
const auto page = (address + this->size) & ~page_mask;
|
|
m_track_end = std::max(m_track_begin, std::min(m_track_end, page));
|
|
}
|
|
m_maybe_cpu_dirty = m_track_begin == m_track_end;
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] bool IsCpuDirty() const { return m_cpu_dirty || m_maybe_cpu_dirty; }
|
|
[[nodiscard]] bool IsDefinitelyCpuDirty() const { return m_cpu_dirty; }
|
|
[[nodiscard]] bool IsMaybeCpuDirty() const { return m_maybe_cpu_dirty; }
|
|
[[nodiscard]] bool NeedsMaybeCpuHash() const {
|
|
return m_maybe_cpu_dirty && !m_maybe_cpu_hash_valid;
|
|
}
|
|
[[nodiscard]] bool IsCpuTrackingComplete() const {
|
|
return m_track_begin == address && m_track_end == address + size;
|
|
}
|
|
void SetMaybeCpuHash(uint64_t hash) {
|
|
if (!NeedsMaybeCpuHash()) {
|
|
EXIT("sampled image cannot initialize maybe-dirty hash\n");
|
|
}
|
|
m_maybe_cpu_hash = hash;
|
|
m_maybe_cpu_hash_valid = true;
|
|
}
|
|
[[nodiscard]] bool ResolveMaybeCpuHash(uint64_t hash) {
|
|
if (!m_maybe_cpu_dirty || !m_maybe_cpu_hash_valid || m_cpu_dirty) {
|
|
EXIT("sampled image cannot resolve maybe-dirty hash\n");
|
|
}
|
|
m_maybe_cpu_dirty = false;
|
|
m_maybe_cpu_hash_valid = false;
|
|
m_cpu_dirty = hash != m_maybe_cpu_hash;
|
|
if (!m_cpu_dirty) {
|
|
m_track_begin = address;
|
|
m_track_end = address + size;
|
|
}
|
|
return m_cpu_dirty;
|
|
}
|
|
|
|
void RefreshComplete() {
|
|
if (!IsCpuDirty()) {
|
|
EXIT("clean sampled image cannot complete a refresh\n");
|
|
}
|
|
m_cpu_dirty = false;
|
|
m_maybe_cpu_dirty = false;
|
|
m_maybe_cpu_hash_valid = false;
|
|
m_track_begin = address;
|
|
m_track_end = address + size;
|
|
}
|
|
|
|
private:
|
|
bool m_cpu_dirty = false;
|
|
bool m_maybe_cpu_dirty = false;
|
|
bool m_maybe_cpu_hash_valid = false;
|
|
uint64_t m_track_begin = 0;
|
|
uint64_t m_track_end = 0;
|
|
uint64_t m_maybe_cpu_hash = 0;
|
|
};
|
|
|
|
struct ImageRetirementRange {
|
|
uint64_t address = 0;
|
|
uint64_t size = 0;
|
|
bool retire = false;
|
|
};
|
|
|
|
struct ImageRetirementConflict {
|
|
size_t retired = SIZE_MAX;
|
|
size_t retained = SIZE_MAX;
|
|
|
|
[[nodiscard]] bool Exists() const { return retired != SIZE_MAX; }
|
|
};
|
|
|
|
[[nodiscard]] inline ImageRetirementConflict
|
|
FindImageRetirementConflict(std::span<const ImageRetirementRange> ranges) {
|
|
for (size_t retired = 0; retired < ranges.size(); retired++) {
|
|
if (!ranges[retired].retire) {
|
|
continue;
|
|
}
|
|
for (size_t retained = 0; retained < ranges.size(); retained++) {
|
|
if (ranges[retained].retire) {
|
|
continue;
|
|
}
|
|
if (ImageRangeOverlaps(ranges[retired].address, ranges[retired].size,
|
|
ranges[retained].address, ranges[retained].size)) {
|
|
return {retired, retained};
|
|
}
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
|
|
} // namespace Libs::Graphics
|
|
|
|
#endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_IMAGE_H_
|