mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-20 08:17:58 -05:00
gpu: Use host address for caching instead of guest address.
This commit is contained in:
@ -13,6 +13,11 @@
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
CachedBufferEntry::CachedBufferEntry(VAddr cpu_addr, std::size_t size, GLintptr offset,
|
||||
std::size_t alignment, u8* host_ptr)
|
||||
: cpu_addr{cpu_addr}, size{size}, offset{offset}, alignment{alignment}, RasterizerCacheObject{
|
||||
host_ptr} {}
|
||||
|
||||
OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, std::size_t size)
|
||||
: RasterizerCache{rasterizer}, stream_buffer(size, true) {}
|
||||
|
||||
@ -26,11 +31,12 @@ GLintptr OGLBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size
|
||||
// TODO: Figure out which size is the best for given games.
|
||||
cache &= size >= 2048;
|
||||
|
||||
const auto& host_ptr{Memory::GetPointer(*cpu_addr)};
|
||||
if (cache) {
|
||||
auto entry = TryGet(*cpu_addr);
|
||||
auto entry = TryGet(host_ptr);
|
||||
if (entry) {
|
||||
if (entry->size >= size && entry->alignment == alignment) {
|
||||
return entry->offset;
|
||||
if (entry->GetSize() >= size && entry->GetAlignment() == alignment) {
|
||||
return entry->GetOffset();
|
||||
}
|
||||
Unregister(entry);
|
||||
}
|
||||
@ -39,17 +45,17 @@ GLintptr OGLBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size
|
||||
AlignBuffer(alignment);
|
||||
const GLintptr uploaded_offset = buffer_offset;
|
||||
|
||||
Memory::ReadBlock(*cpu_addr, buffer_ptr, size);
|
||||
if (!host_ptr) {
|
||||
return uploaded_offset;
|
||||
}
|
||||
|
||||
std::memcpy(buffer_ptr, host_ptr, size);
|
||||
buffer_ptr += size;
|
||||
buffer_offset += size;
|
||||
|
||||
if (cache) {
|
||||
auto entry = std::make_shared<CachedBufferEntry>();
|
||||
entry->offset = uploaded_offset;
|
||||
entry->size = size;
|
||||
entry->alignment = alignment;
|
||||
entry->addr = *cpu_addr;
|
||||
auto entry = std::make_shared<CachedBufferEntry>(*cpu_addr, size, uploaded_offset,
|
||||
alignment, host_ptr);
|
||||
Register(entry);
|
||||
}
|
||||
|
||||
|
@ -17,22 +17,39 @@ namespace OpenGL {
|
||||
|
||||
class RasterizerOpenGL;
|
||||
|
||||
struct CachedBufferEntry final : public RasterizerCacheObject {
|
||||
VAddr GetAddr() const override {
|
||||
return addr;
|
||||
class CachedBufferEntry final : public RasterizerCacheObject {
|
||||
public:
|
||||
explicit CachedBufferEntry(VAddr cpu_addr, std::size_t size, GLintptr offset,
|
||||
std::size_t alignment, u8* host_ptr);
|
||||
|
||||
VAddr GetCpuAddr() const override {
|
||||
return cpu_addr;
|
||||
}
|
||||
|
||||
std::size_t GetSizeInBytes() const override {
|
||||
return size;
|
||||
}
|
||||
|
||||
std::size_t GetSize() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
GLintptr GetOffset() const {
|
||||
return offset;
|
||||
}
|
||||
|
||||
std::size_t GetAlignment() const {
|
||||
return alignment;
|
||||
}
|
||||
|
||||
// We do not have to flush this cache as things in it are never modified by us.
|
||||
void Flush() override {}
|
||||
|
||||
VAddr addr;
|
||||
std::size_t size;
|
||||
GLintptr offset;
|
||||
std::size_t alignment;
|
||||
private:
|
||||
VAddr cpu_addr{};
|
||||
std::size_t size{};
|
||||
GLintptr offset{};
|
||||
std::size_t alignment{};
|
||||
};
|
||||
|
||||
class OGLBufferCache final : public RasterizerCache<std::shared_ptr<CachedBufferEntry>> {
|
||||
|
@ -15,12 +15,13 @@
|
||||
|
||||
namespace OpenGL {
|
||||
|
||||
CachedGlobalRegion::CachedGlobalRegion(VAddr addr, u32 size) : addr{addr}, size{size} {
|
||||
CachedGlobalRegion::CachedGlobalRegion(VAddr cpu_addr, u32 size, u8* host_ptr)
|
||||
: cpu_addr{cpu_addr}, size{size}, RasterizerCacheObject{host_ptr} {
|
||||
buffer.Create();
|
||||
// Bind and unbind the buffer so it gets allocated by the driver
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer.handle);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
LabelGLObject(GL_BUFFER, buffer.handle, addr, "GlobalMemory");
|
||||
LabelGLObject(GL_BUFFER, buffer.handle, cpu_addr, "GlobalMemory");
|
||||
}
|
||||
|
||||
void CachedGlobalRegion::Reload(u32 size_) {
|
||||
@ -35,7 +36,7 @@ void CachedGlobalRegion::Reload(u32 size_) {
|
||||
|
||||
// TODO(Rodrigo): Get rid of Memory::GetPointer with a staging buffer
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer.handle);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, size, Memory::GetPointer(addr), GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, size, GetHostPtr(), GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
GlobalRegion GlobalRegionCacheOpenGL::TryGetReservedGlobalRegion(VAddr addr, u32 size) const {
|
||||
@ -46,11 +47,11 @@ GlobalRegion GlobalRegionCacheOpenGL::TryGetReservedGlobalRegion(VAddr addr, u32
|
||||
return search->second;
|
||||
}
|
||||
|
||||
GlobalRegion GlobalRegionCacheOpenGL::GetUncachedGlobalRegion(VAddr addr, u32 size) {
|
||||
GlobalRegion GlobalRegionCacheOpenGL::GetUncachedGlobalRegion(VAddr addr, u32 size, u8* host_ptr) {
|
||||
GlobalRegion region{TryGetReservedGlobalRegion(addr, size)};
|
||||
if (!region) {
|
||||
// No reserved surface available, create a new one and reserve it
|
||||
region = std::make_shared<CachedGlobalRegion>(addr, size);
|
||||
region = std::make_shared<CachedGlobalRegion>(addr, size, host_ptr);
|
||||
ReserveGlobalRegion(region);
|
||||
}
|
||||
region->Reload(size);
|
||||
@ -58,7 +59,7 @@ GlobalRegion GlobalRegionCacheOpenGL::GetUncachedGlobalRegion(VAddr addr, u32 si
|
||||
}
|
||||
|
||||
void GlobalRegionCacheOpenGL::ReserveGlobalRegion(GlobalRegion region) {
|
||||
reserve.insert_or_assign(region->GetAddr(), std::move(region));
|
||||
reserve.insert_or_assign(region->GetCpuAddr(), std::move(region));
|
||||
}
|
||||
|
||||
GlobalRegionCacheOpenGL::GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer)
|
||||
@ -80,11 +81,12 @@ GlobalRegion GlobalRegionCacheOpenGL::GetGlobalRegion(
|
||||
ASSERT(actual_addr);
|
||||
|
||||
// Look up global region in the cache based on address
|
||||
GlobalRegion region = TryGet(*actual_addr);
|
||||
const auto& host_ptr{Memory::GetPointer(*actual_addr)};
|
||||
GlobalRegion region{TryGet(host_ptr)};
|
||||
|
||||
if (!region) {
|
||||
// No global region found - create a new one
|
||||
region = GetUncachedGlobalRegion(*actual_addr, size);
|
||||
region = GetUncachedGlobalRegion(*actual_addr, size, host_ptr);
|
||||
Register(region);
|
||||
}
|
||||
|
||||
|
@ -27,14 +27,12 @@ using GlobalRegion = std::shared_ptr<CachedGlobalRegion>;
|
||||
|
||||
class CachedGlobalRegion final : public RasterizerCacheObject {
|
||||
public:
|
||||
explicit CachedGlobalRegion(VAddr addr, u32 size);
|
||||
explicit CachedGlobalRegion(VAddr cpu_addr, u32 size, u8* host_ptr);
|
||||
|
||||
/// Gets the address of the shader in guest memory, required for cache management
|
||||
VAddr GetAddr() const override {
|
||||
return addr;
|
||||
VAddr GetCpuAddr() const override {
|
||||
return cpu_addr;
|
||||
}
|
||||
|
||||
/// Gets the size of the shader in guest memory, required for cache management
|
||||
std::size_t GetSizeInBytes() const override {
|
||||
return size;
|
||||
}
|
||||
@ -53,9 +51,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
VAddr addr{};
|
||||
VAddr cpu_addr{};
|
||||
u32 size{};
|
||||
|
||||
OGLBuffer buffer;
|
||||
};
|
||||
|
||||
@ -69,7 +66,7 @@ public:
|
||||
|
||||
private:
|
||||
GlobalRegion TryGetReservedGlobalRegion(VAddr addr, u32 size) const;
|
||||
GlobalRegion GetUncachedGlobalRegion(VAddr addr, u32 size);
|
||||
GlobalRegion GetUncachedGlobalRegion(VAddr addr, u32 size, u8* host_ptr);
|
||||
void ReserveGlobalRegion(GlobalRegion region);
|
||||
|
||||
std::unordered_map<VAddr, GlobalRegion> reserve;
|
||||
|
@ -449,7 +449,7 @@ static constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
|
||||
return boost::make_iterator_range(map.equal_range(interval));
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta) {
|
||||
void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
|
||||
const u64 page_start{addr >> Memory::PAGE_BITS};
|
||||
const u64 page_end{(addr + size + Memory::PAGE_SIZE - 1) >> Memory::PAGE_BITS};
|
||||
|
||||
@ -747,12 +747,12 @@ void RasterizerOpenGL::DrawArrays() {
|
||||
|
||||
void RasterizerOpenGL::FlushAll() {}
|
||||
|
||||
void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) {
|
||||
void RasterizerOpenGL::FlushRegion(CacheAddr addr, u64 size) {
|
||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
||||
res_cache.FlushRegion(addr, size);
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) {
|
||||
void RasterizerOpenGL::InvalidateRegion(CacheAddr addr, u64 size) {
|
||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
||||
res_cache.InvalidateRegion(addr, size);
|
||||
shader_cache.InvalidateRegion(addr, size);
|
||||
@ -760,7 +760,7 @@ void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) {
|
||||
buffer_cache.InvalidateRegion(addr, size);
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) {
|
||||
void RasterizerOpenGL::FlushAndInvalidateRegion(CacheAddr addr, u64 size) {
|
||||
FlushRegion(addr, size);
|
||||
InvalidateRegion(addr, size);
|
||||
}
|
||||
@ -782,7 +782,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
|
||||
|
||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
||||
|
||||
const auto& surface{res_cache.TryFindFramebufferSurface(framebuffer_addr)};
|
||||
const auto& surface{res_cache.TryFindFramebufferSurface(Memory::GetPointer(framebuffer_addr))};
|
||||
if (!surface) {
|
||||
return {};
|
||||
}
|
||||
|
@ -57,9 +57,9 @@ public:
|
||||
void DrawArrays() override;
|
||||
void Clear() override;
|
||||
void FlushAll() override;
|
||||
void FlushRegion(VAddr addr, u64 size) override;
|
||||
void InvalidateRegion(VAddr addr, u64 size) override;
|
||||
void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
|
||||
void FlushRegion(CacheAddr addr, u64 size) override;
|
||||
void InvalidateRegion(CacheAddr addr, u64 size) override;
|
||||
void FlushAndInvalidateRegion(CacheAddr addr, u64 size) override;
|
||||
bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
|
||||
const Tegra::Engines::Fermi2D::Regs::Surface& dst,
|
||||
const Common::Rectangle<u32>& src_rect,
|
||||
@ -67,7 +67,7 @@ public:
|
||||
bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
|
||||
u32 pixel_stride) override;
|
||||
bool AccelerateDrawBatch(bool is_indexed) override;
|
||||
void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta) override;
|
||||
void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
|
||||
void LoadDiskResources(const std::atomic_bool& stop_loading,
|
||||
const VideoCore::DiskResourceLoadCallback& callback) override;
|
||||
|
||||
|
@ -61,6 +61,7 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
|
||||
|
||||
addr = cpu_addr ? *cpu_addr : 0;
|
||||
gpu_addr = gpu_addr_;
|
||||
host_ptr = Memory::GetPointer(addr);
|
||||
size_in_bytes = SizeInBytesRaw();
|
||||
|
||||
if (IsPixelFormatASTC(pixel_format)) {
|
||||
@ -563,8 +564,8 @@ void RasterizerCacheOpenGL::CopySurface(const Surface& src_surface, const Surfac
|
||||
}
|
||||
|
||||
CachedSurface::CachedSurface(const SurfaceParams& params)
|
||||
: params(params), gl_target(SurfaceTargetToGL(params.target)),
|
||||
cached_size_in_bytes(params.size_in_bytes) {
|
||||
: params{params}, gl_target{SurfaceTargetToGL(params.target)},
|
||||
cached_size_in_bytes{params.size_in_bytes}, RasterizerCacheObject{params.host_ptr} {
|
||||
texture.Create(gl_target);
|
||||
|
||||
// TODO(Rodrigo): Using params.GetRect() returns a different size than using its Mip*(0)
|
||||
@ -633,10 +634,9 @@ void CachedSurface::LoadGLBuffer() {
|
||||
const u32 bpp = params.GetFormatBpp() / 8;
|
||||
const u32 copy_size = params.width * bpp;
|
||||
if (params.pitch == copy_size) {
|
||||
std::memcpy(gl_buffer[0].data(), Memory::GetPointer(params.addr),
|
||||
params.size_in_bytes_gl);
|
||||
std::memcpy(gl_buffer[0].data(), params.host_ptr, params.size_in_bytes_gl);
|
||||
} else {
|
||||
const u8* start = Memory::GetPointer(params.addr);
|
||||
const u8* start{params.host_ptr};
|
||||
u8* write_to = gl_buffer[0].data();
|
||||
for (u32 h = params.height; h > 0; h--) {
|
||||
std::memcpy(write_to, start, copy_size);
|
||||
@ -680,8 +680,6 @@ void CachedSurface::FlushGLBuffer() {
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
Tegra::Texture::ConvertFromHostToGuest(gl_buffer[0].data(), params.pixel_format, params.width,
|
||||
params.height, params.depth, true, true);
|
||||
const u8* const texture_src_data = Memory::GetPointer(params.addr);
|
||||
ASSERT(texture_src_data);
|
||||
if (params.is_tiled) {
|
||||
ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}",
|
||||
params.block_width, static_cast<u32>(params.target));
|
||||
@ -691,9 +689,9 @@ void CachedSurface::FlushGLBuffer() {
|
||||
const u32 bpp = params.GetFormatBpp() / 8;
|
||||
const u32 copy_size = params.width * bpp;
|
||||
if (params.pitch == copy_size) {
|
||||
std::memcpy(Memory::GetPointer(params.addr), gl_buffer[0].data(), GetSizeInBytes());
|
||||
std::memcpy(params.host_ptr, gl_buffer[0].data(), GetSizeInBytes());
|
||||
} else {
|
||||
u8* start = Memory::GetPointer(params.addr);
|
||||
u8* start{params.host_ptr};
|
||||
const u8* read_to = gl_buffer[0].data();
|
||||
for (u32 h = params.height; h > 0; h--) {
|
||||
std::memcpy(start, read_to, copy_size);
|
||||
@ -932,7 +930,7 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, bool pres
|
||||
}
|
||||
|
||||
// Look up surface in the cache based on address
|
||||
Surface surface{TryGet(params.addr)};
|
||||
Surface surface{TryGet(params.host_ptr)};
|
||||
if (surface) {
|
||||
if (surface->GetSurfaceParams().IsCompatibleSurface(params)) {
|
||||
// Use the cached surface as-is unless it's not synced with memory
|
||||
@ -986,7 +984,7 @@ void RasterizerCacheOpenGL::FastLayeredCopySurface(const Surface& src_surface,
|
||||
for (u32 layer = 0; layer < dst_params.depth; layer++) {
|
||||
for (u32 mipmap = 0; mipmap < dst_params.max_mip_level; mipmap++) {
|
||||
const VAddr sub_address = address + dst_params.GetMipmapLevelOffset(mipmap);
|
||||
const Surface& copy = TryGet(sub_address);
|
||||
const Surface& copy = TryGet(Memory::GetPointer(sub_address));
|
||||
if (!copy)
|
||||
continue;
|
||||
const auto& src_params{copy->GetSurfaceParams()};
|
||||
@ -1163,7 +1161,8 @@ void RasterizerCacheOpenGL::AccurateCopySurface(const Surface& src_surface,
|
||||
const auto& dst_params{dst_surface->GetSurfaceParams()};
|
||||
|
||||
// Flush enough memory for both the source and destination surface
|
||||
FlushRegion(src_params.addr, std::max(src_params.MemorySize(), dst_params.MemorySize()));
|
||||
FlushRegion(ToCacheAddr(src_params.host_ptr),
|
||||
std::max(src_params.MemorySize(), dst_params.MemorySize()));
|
||||
|
||||
LoadSurface(dst_surface);
|
||||
}
|
||||
@ -1215,8 +1214,8 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
|
||||
return new_surface;
|
||||
}
|
||||
|
||||
Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(VAddr addr) const {
|
||||
return TryGet(addr);
|
||||
Surface RasterizerCacheOpenGL::TryFindFramebufferSurface(const u8* host_ptr) const {
|
||||
return TryGet(host_ptr);
|
||||
}
|
||||
|
||||
void RasterizerCacheOpenGL::ReserveSurface(const Surface& surface) {
|
||||
@ -1267,7 +1266,7 @@ static bool LayerFitReinterpretSurface(RasterizerCacheOpenGL& cache, const Surfa
|
||||
src_params.height == dst_params.MipHeight(*level) &&
|
||||
src_params.block_height >= dst_params.MipBlockHeight(*level)) {
|
||||
const std::optional<u32> slot =
|
||||
TryFindBestLayer(render_surface->GetAddr(), dst_params, *level);
|
||||
TryFindBestLayer(render_surface->GetCpuAddr(), dst_params, *level);
|
||||
if (slot.has_value()) {
|
||||
glCopyImageSubData(render_surface->Texture().handle,
|
||||
SurfaceTargetToGL(src_params.target), 0, 0, 0, 0,
|
||||
@ -1283,8 +1282,8 @@ static bool LayerFitReinterpretSurface(RasterizerCacheOpenGL& cache, const Surfa
|
||||
}
|
||||
|
||||
static bool IsReinterpretInvalid(const Surface render_surface, const Surface blitted_surface) {
|
||||
const VAddr bound1 = blitted_surface->GetAddr() + blitted_surface->GetMemorySize();
|
||||
const VAddr bound2 = render_surface->GetAddr() + render_surface->GetMemorySize();
|
||||
const VAddr bound1 = blitted_surface->GetCpuAddr() + blitted_surface->GetMemorySize();
|
||||
const VAddr bound2 = render_surface->GetCpuAddr() + render_surface->GetMemorySize();
|
||||
if (bound2 > bound1)
|
||||
return true;
|
||||
const auto& dst_params = blitted_surface->GetSurfaceParams();
|
||||
@ -1327,7 +1326,8 @@ void RasterizerCacheOpenGL::SignalPreDrawCall() {
|
||||
void RasterizerCacheOpenGL::SignalPostDrawCall() {
|
||||
for (u32 i = 0; i < Maxwell::NumRenderTargets; i++) {
|
||||
if (current_color_buffers[i] != nullptr) {
|
||||
Surface intersect = CollideOnReinterpretedSurface(current_color_buffers[i]->GetAddr());
|
||||
Surface intersect =
|
||||
CollideOnReinterpretedSurface(current_color_buffers[i]->GetCacheAddr());
|
||||
if (intersect != nullptr) {
|
||||
PartialReinterpretSurface(current_color_buffers[i], intersect);
|
||||
texception = true;
|
||||
|
@ -297,6 +297,7 @@ struct SurfaceParams {
|
||||
bool srgb_conversion;
|
||||
// Parameters used for caching
|
||||
VAddr addr;
|
||||
u8* host_ptr;
|
||||
Tegra::GPUVAddr gpu_addr;
|
||||
std::size_t size_in_bytes;
|
||||
std::size_t size_in_bytes_gl;
|
||||
@ -345,9 +346,9 @@ class RasterizerOpenGL;
|
||||
|
||||
class CachedSurface final : public RasterizerCacheObject {
|
||||
public:
|
||||
CachedSurface(const SurfaceParams& params);
|
||||
explicit CachedSurface(const SurfaceParams& params);
|
||||
|
||||
VAddr GetAddr() const override {
|
||||
VAddr GetCpuAddr() const override {
|
||||
return params.addr;
|
||||
}
|
||||
|
||||
@ -449,7 +450,7 @@ public:
|
||||
Surface GetColorBufferSurface(std::size_t index, bool preserve_contents);
|
||||
|
||||
/// Tries to find a framebuffer using on the provided CPU address
|
||||
Surface TryFindFramebufferSurface(VAddr addr) const;
|
||||
Surface TryFindFramebufferSurface(const u8* host_ptr) const;
|
||||
|
||||
/// Copies the contents of one surface to another
|
||||
void FermiCopySurface(const Tegra::Engines::Fermi2D::Regs::Surface& src_config,
|
||||
@ -506,12 +507,12 @@ private:
|
||||
std::array<Surface, Maxwell::NumRenderTargets> current_color_buffers;
|
||||
Surface last_depth_buffer;
|
||||
|
||||
using SurfaceIntervalCache = boost::icl::interval_map<VAddr, Surface>;
|
||||
using SurfaceIntervalCache = boost::icl::interval_map<CacheAddr, Surface>;
|
||||
using SurfaceInterval = typename SurfaceIntervalCache::interval_type;
|
||||
|
||||
static auto GetReinterpretInterval(const Surface& object) {
|
||||
return SurfaceInterval::right_open(object->GetAddr() + 1,
|
||||
object->GetAddr() + object->GetMemorySize() - 1);
|
||||
return SurfaceInterval::right_open(object->GetCacheAddr() + 1,
|
||||
object->GetCacheAddr() + object->GetMemorySize() - 1);
|
||||
}
|
||||
|
||||
// Reinterpreted surfaces are very fragil as the game may keep rendering into them.
|
||||
@ -523,7 +524,7 @@ private:
|
||||
reinterpret_surface->MarkReinterpreted();
|
||||
}
|
||||
|
||||
Surface CollideOnReinterpretedSurface(VAddr addr) const {
|
||||
Surface CollideOnReinterpretedSurface(CacheAddr addr) const {
|
||||
const SurfaceInterval interval{addr};
|
||||
for (auto& pair :
|
||||
boost::make_iterator_range(reinterpreted_surfaces.equal_range(interval))) {
|
||||
|
@ -42,9 +42,9 @@ VAddr GetShaderAddress(Maxwell::ShaderProgram program) {
|
||||
}
|
||||
|
||||
/// Gets the shader program code from memory for the specified address
|
||||
ProgramCode GetShaderCode(VAddr addr) {
|
||||
ProgramCode GetShaderCode(const u8* host_ptr) {
|
||||
ProgramCode program_code(VideoCommon::Shader::MAX_PROGRAM_LENGTH);
|
||||
Memory::ReadBlock(addr, program_code.data(), program_code.size() * sizeof(u64));
|
||||
std::memcpy(program_code.data(), host_ptr, program_code.size() * sizeof(u64));
|
||||
return program_code;
|
||||
}
|
||||
|
||||
@ -214,12 +214,13 @@ std::set<GLenum> GetSupportedFormats() {
|
||||
|
||||
} // namespace
|
||||
|
||||
CachedShader::CachedShader(VAddr addr, u64 unique_identifier, Maxwell::ShaderProgram program_type,
|
||||
ShaderDiskCacheOpenGL& disk_cache,
|
||||
CachedShader::CachedShader(VAddr guest_addr, u64 unique_identifier,
|
||||
Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache,
|
||||
const PrecompiledPrograms& precompiled_programs,
|
||||
ProgramCode&& program_code, ProgramCode&& program_code_b)
|
||||
: addr{addr}, unique_identifier{unique_identifier}, program_type{program_type},
|
||||
disk_cache{disk_cache}, precompiled_programs{precompiled_programs} {
|
||||
ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr)
|
||||
: host_ptr{host_ptr}, guest_addr{guest_addr}, unique_identifier{unique_identifier},
|
||||
program_type{program_type}, disk_cache{disk_cache},
|
||||
precompiled_programs{precompiled_programs}, RasterizerCacheObject{host_ptr} {
|
||||
|
||||
const std::size_t code_size = CalculateProgramSize(program_code);
|
||||
const std::size_t code_size_b =
|
||||
@ -243,12 +244,13 @@ CachedShader::CachedShader(VAddr addr, u64 unique_identifier, Maxwell::ShaderPro
|
||||
disk_cache.SaveRaw(raw);
|
||||
}
|
||||
|
||||
CachedShader::CachedShader(VAddr addr, u64 unique_identifier, Maxwell::ShaderProgram program_type,
|
||||
ShaderDiskCacheOpenGL& disk_cache,
|
||||
CachedShader::CachedShader(VAddr guest_addr, u64 unique_identifier,
|
||||
Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache,
|
||||
const PrecompiledPrograms& precompiled_programs,
|
||||
GLShader::ProgramResult result)
|
||||
: addr{addr}, unique_identifier{unique_identifier}, program_type{program_type},
|
||||
disk_cache{disk_cache}, precompiled_programs{precompiled_programs} {
|
||||
GLShader::ProgramResult result, u8* host_ptr)
|
||||
: guest_addr{guest_addr}, unique_identifier{unique_identifier}, program_type{program_type},
|
||||
disk_cache{disk_cache}, precompiled_programs{precompiled_programs}, RasterizerCacheObject{
|
||||
host_ptr} {
|
||||
|
||||
code = std::move(result.first);
|
||||
entries = result.second;
|
||||
@ -271,7 +273,7 @@ std::tuple<GLuint, BaseBindings> CachedShader::GetProgramHandle(GLenum primitive
|
||||
disk_cache.SaveUsage(GetUsage(primitive_mode, base_bindings));
|
||||
}
|
||||
|
||||
LabelGLObject(GL_PROGRAM, program->handle, addr);
|
||||
LabelGLObject(GL_PROGRAM, program->handle, guest_addr);
|
||||
}
|
||||
|
||||
handle = program->handle;
|
||||
@ -323,7 +325,7 @@ GLuint CachedShader::LazyGeometryProgram(CachedProgram& target_program, BaseBind
|
||||
disk_cache.SaveUsage(GetUsage(primitive_mode, base_bindings));
|
||||
}
|
||||
|
||||
LabelGLObject(GL_PROGRAM, target_program->handle, addr, debug_name);
|
||||
LabelGLObject(GL_PROGRAM, target_program->handle, guest_addr, debug_name);
|
||||
|
||||
return target_program->handle;
|
||||
};
|
||||
@ -489,14 +491,17 @@ Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
|
||||
const VAddr program_addr{GetShaderAddress(program)};
|
||||
|
||||
// Look up shader in the cache based on address
|
||||
Shader shader{TryGet(program_addr)};
|
||||
const auto& host_ptr{Memory::GetPointer(program_addr)};
|
||||
Shader shader{TryGet(host_ptr)};
|
||||
|
||||
if (!shader) {
|
||||
// No shader found - create a new one
|
||||
ProgramCode program_code = GetShaderCode(program_addr);
|
||||
const auto& host_ptr{Memory::GetPointer(program_addr)};
|
||||
ProgramCode program_code{GetShaderCode(host_ptr)};
|
||||
ProgramCode program_code_b;
|
||||
if (program == Maxwell::ShaderProgram::VertexA) {
|
||||
program_code_b = GetShaderCode(GetShaderAddress(Maxwell::ShaderProgram::VertexB));
|
||||
program_code_b = GetShaderCode(
|
||||
Memory::GetPointer(GetShaderAddress(Maxwell::ShaderProgram::VertexB)));
|
||||
}
|
||||
const u64 unique_identifier = GetUniqueIdentifier(program, program_code, program_code_b);
|
||||
|
||||
@ -504,11 +509,11 @@ Shader ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) {
|
||||
if (found != precompiled_shaders.end()) {
|
||||
shader =
|
||||
std::make_shared<CachedShader>(program_addr, unique_identifier, program, disk_cache,
|
||||
precompiled_programs, found->second);
|
||||
precompiled_programs, found->second, host_ptr);
|
||||
} else {
|
||||
shader = std::make_shared<CachedShader>(
|
||||
program_addr, unique_identifier, program, disk_cache, precompiled_programs,
|
||||
std::move(program_code), std::move(program_code_b));
|
||||
std::move(program_code), std::move(program_code_b), host_ptr);
|
||||
}
|
||||
Register(shader);
|
||||
}
|
||||
|
@ -39,18 +39,18 @@ using PrecompiledShaders = std::unordered_map<u64, GLShader::ProgramResult>;
|
||||
|
||||
class CachedShader final : public RasterizerCacheObject {
|
||||
public:
|
||||
explicit CachedShader(VAddr addr, u64 unique_identifier, Maxwell::ShaderProgram program_type,
|
||||
ShaderDiskCacheOpenGL& disk_cache,
|
||||
explicit CachedShader(VAddr guest_addr, u64 unique_identifier,
|
||||
Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache,
|
||||
const PrecompiledPrograms& precompiled_programs,
|
||||
ProgramCode&& program_code, ProgramCode&& program_code_b);
|
||||
ProgramCode&& program_code, ProgramCode&& program_code_b, u8* host_ptr);
|
||||
|
||||
explicit CachedShader(VAddr addr, u64 unique_identifier, Maxwell::ShaderProgram program_type,
|
||||
ShaderDiskCacheOpenGL& disk_cache,
|
||||
explicit CachedShader(VAddr guest_addr, u64 unique_identifier,
|
||||
Maxwell::ShaderProgram program_type, ShaderDiskCacheOpenGL& disk_cache,
|
||||
const PrecompiledPrograms& precompiled_programs,
|
||||
GLShader::ProgramResult result);
|
||||
GLShader::ProgramResult result, u8* host_ptr);
|
||||
|
||||
VAddr GetAddr() const override {
|
||||
return addr;
|
||||
VAddr GetCpuAddr() const override {
|
||||
return guest_addr;
|
||||
}
|
||||
|
||||
std::size_t GetSizeInBytes() const override {
|
||||
@ -91,7 +91,8 @@ private:
|
||||
|
||||
ShaderDiskCacheUsage GetUsage(GLenum primitive_mode, BaseBindings base_bindings) const;
|
||||
|
||||
VAddr addr{};
|
||||
u8* host_ptr{};
|
||||
VAddr guest_addr{};
|
||||
u64 unique_identifier{};
|
||||
Maxwell::ShaderProgram program_type{};
|
||||
ShaderDiskCacheOpenGL& disk_cache;
|
||||
|
Reference in New Issue
Block a user