mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	Merge pull request #7805 from FernandoS27/rodrigo-failed-me
Inline2Memory: Flush before writing buffer.
This commit is contained in:
		@@ -131,6 +131,8 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void DownloadMemory(VAddr cpu_addr, u64 size);
 | 
					    void DownloadMemory(VAddr cpu_addr, u64 size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool InlineMemory(VAddr dest_address, size_t copy_size, std::span<u8> inlined_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size);
 | 
					    void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void DisableGraphicsUniformBuffer(size_t stage, u32 index);
 | 
					    void DisableGraphicsUniformBuffer(size_t stage, u32 index);
 | 
				
			||||||
@@ -808,6 +810,8 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    MICROPROFILE_SCOPE(GPU_DownloadMemory);
 | 
					    MICROPROFILE_SCOPE(GPU_DownloadMemory);
 | 
				
			||||||
 | 
					    const bool is_accuracy_normal =
 | 
				
			||||||
 | 
					        Settings::values.gpu_accuracy.GetValue() == Settings::GPUAccuracy::Normal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    boost::container::small_vector<std::pair<BufferCopy, BufferId>, 1> downloads;
 | 
					    boost::container::small_vector<std::pair<BufferCopy, BufferId>, 1> downloads;
 | 
				
			||||||
    u64 total_size_bytes = 0;
 | 
					    u64 total_size_bytes = 0;
 | 
				
			||||||
@@ -819,6 +823,9 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
 | 
				
			|||||||
            ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) {
 | 
					            ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) {
 | 
				
			||||||
                buffer.ForEachDownloadRangeAndClear(
 | 
					                buffer.ForEachDownloadRangeAndClear(
 | 
				
			||||||
                    cpu_addr, size, [&](u64 range_offset, u64 range_size) {
 | 
					                    cpu_addr, size, [&](u64 range_offset, u64 range_size) {
 | 
				
			||||||
 | 
					                        if (is_accuracy_normal) {
 | 
				
			||||||
 | 
					                            return;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        const VAddr buffer_addr = buffer.CpuAddr();
 | 
					                        const VAddr buffer_addr = buffer.CpuAddr();
 | 
				
			||||||
                        const auto add_download = [&](VAddr start, VAddr end) {
 | 
					                        const auto add_download = [&](VAddr start, VAddr end) {
 | 
				
			||||||
                            const u64 new_offset = start - buffer_addr;
 | 
					                            const u64 new_offset = start - buffer_addr;
 | 
				
			||||||
@@ -1417,10 +1424,8 @@ void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 s
 | 
				
			|||||||
    const IntervalType base_interval{cpu_addr, cpu_addr + size};
 | 
					    const IntervalType base_interval{cpu_addr, cpu_addr + size};
 | 
				
			||||||
    common_ranges.add(base_interval);
 | 
					    common_ranges.add(base_interval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const bool is_accuracy_high =
 | 
					 | 
				
			||||||
        Settings::values.gpu_accuracy.GetValue() == Settings::GPUAccuracy::High;
 | 
					 | 
				
			||||||
    const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue();
 | 
					    const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue();
 | 
				
			||||||
    if (!is_async && !is_accuracy_high) {
 | 
					    if (!is_async) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    uncommitted_ranges.add(base_interval);
 | 
					    uncommitted_ranges.add(base_interval);
 | 
				
			||||||
@@ -1643,6 +1648,42 @@ void BufferCache<P>::MappedUploadMemory(Buffer& buffer, u64 total_size_bytes,
 | 
				
			|||||||
    runtime.CopyBuffer(buffer, upload_staging.buffer, copies);
 | 
					    runtime.CopyBuffer(buffer, upload_staging.buffer, copies);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <class P>
 | 
				
			||||||
 | 
					bool BufferCache<P>::InlineMemory(VAddr dest_address, size_t copy_size,
 | 
				
			||||||
 | 
					                                  std::span<u8> inlined_buffer) {
 | 
				
			||||||
 | 
					    const bool is_dirty = IsRegionRegistered(dest_address, copy_size);
 | 
				
			||||||
 | 
					    if (!is_dirty) {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!IsRegionGpuModified(dest_address, copy_size)) {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const IntervalType subtract_interval{dest_address, dest_address + copy_size};
 | 
				
			||||||
 | 
					    ClearDownload(subtract_interval);
 | 
				
			||||||
 | 
					    common_ranges.subtract(subtract_interval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BufferId buffer_id = FindBuffer(dest_address, static_cast<u32>(copy_size));
 | 
				
			||||||
 | 
					    auto& buffer = slot_buffers[buffer_id];
 | 
				
			||||||
 | 
					    SynchronizeBuffer(buffer, dest_address, static_cast<u32>(copy_size));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if constexpr (USE_MEMORY_MAPS) {
 | 
				
			||||||
 | 
					        std::array copies{BufferCopy{
 | 
				
			||||||
 | 
					            .src_offset = 0,
 | 
				
			||||||
 | 
					            .dst_offset = buffer.Offset(dest_address),
 | 
				
			||||||
 | 
					            .size = copy_size,
 | 
				
			||||||
 | 
					        }};
 | 
				
			||||||
 | 
					        auto upload_staging = runtime.UploadStagingBuffer(copy_size);
 | 
				
			||||||
 | 
					        u8* const src_pointer = upload_staging.mapped_span.data();
 | 
				
			||||||
 | 
					        std::memcpy(src_pointer, inlined_buffer.data(), copy_size);
 | 
				
			||||||
 | 
					        runtime.CopyBuffer(buffer, upload_staging.buffer, copies);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        buffer.ImmediateUpload(buffer.Offset(dest_address), inlined_buffer.first(copy_size));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <class P>
 | 
					template <class P>
 | 
				
			||||||
void BufferCache<P>::DownloadBufferMemory(Buffer& buffer) {
 | 
					void BufferCache<P>::DownloadBufferMemory(Buffer& buffer) {
 | 
				
			||||||
    DownloadBufferMemory(buffer, buffer.CpuAddr(), buffer.SizeBytes());
 | 
					    DownloadBufferMemory(buffer, buffer.CpuAddr(), buffer.SizeBytes());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
#include "common/assert.h"
 | 
					#include "common/assert.h"
 | 
				
			||||||
#include "video_core/engines/engine_upload.h"
 | 
					#include "video_core/engines/engine_upload.h"
 | 
				
			||||||
#include "video_core/memory_manager.h"
 | 
					#include "video_core/memory_manager.h"
 | 
				
			||||||
 | 
					#include "video_core/rasterizer_interface.h"
 | 
				
			||||||
#include "video_core/textures/decoders.h"
 | 
					#include "video_core/textures/decoders.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Tegra::Engines::Upload {
 | 
					namespace Tegra::Engines::Upload {
 | 
				
			||||||
@@ -16,6 +17,10 @@ State::State(MemoryManager& memory_manager_, Registers& regs_)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
State::~State() = default;
 | 
					State::~State() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void State::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
 | 
				
			||||||
 | 
					    rasterizer = rasterizer_;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void State::ProcessExec(const bool is_linear_) {
 | 
					void State::ProcessExec(const bool is_linear_) {
 | 
				
			||||||
    write_offset = 0;
 | 
					    write_offset = 0;
 | 
				
			||||||
    copy_size = regs.line_length_in * regs.line_count;
 | 
					    copy_size = regs.line_length_in * regs.line_count;
 | 
				
			||||||
@@ -32,7 +37,7 @@ void State::ProcessData(const u32 data, const bool is_last_call) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    const GPUVAddr address{regs.dest.Address()};
 | 
					    const GPUVAddr address{regs.dest.Address()};
 | 
				
			||||||
    if (is_linear) {
 | 
					    if (is_linear) {
 | 
				
			||||||
        memory_manager.WriteBlock(address, inner_buffer.data(), copy_size);
 | 
					        rasterizer->AccelerateInlineToMemory(address, copy_size, inner_buffer);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        UNIMPLEMENTED_IF(regs.dest.z != 0);
 | 
					        UNIMPLEMENTED_IF(regs.dest.z != 0);
 | 
				
			||||||
        UNIMPLEMENTED_IF(regs.dest.depth != 1);
 | 
					        UNIMPLEMENTED_IF(regs.dest.depth != 1);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,10 @@ namespace Tegra {
 | 
				
			|||||||
class MemoryManager;
 | 
					class MemoryManager;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace VideoCore {
 | 
				
			||||||
 | 
					class RasterizerInterface;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Tegra::Engines::Upload {
 | 
					namespace Tegra::Engines::Upload {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Registers {
 | 
					struct Registers {
 | 
				
			||||||
@@ -60,6 +64,9 @@ public:
 | 
				
			|||||||
    void ProcessExec(bool is_linear_);
 | 
					    void ProcessExec(bool is_linear_);
 | 
				
			||||||
    void ProcessData(u32 data, bool is_last_call);
 | 
					    void ProcessData(u32 data, bool is_last_call);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Binds a rasterizer to this engine.
 | 
				
			||||||
 | 
					    void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    u32 write_offset = 0;
 | 
					    u32 write_offset = 0;
 | 
				
			||||||
    u32 copy_size = 0;
 | 
					    u32 copy_size = 0;
 | 
				
			||||||
@@ -68,6 +75,7 @@ private:
 | 
				
			|||||||
    bool is_linear = false;
 | 
					    bool is_linear = false;
 | 
				
			||||||
    Registers& regs;
 | 
					    Registers& regs;
 | 
				
			||||||
    MemoryManager& memory_manager;
 | 
					    MemoryManager& memory_manager;
 | 
				
			||||||
 | 
					    VideoCore::RasterizerInterface* rasterizer = nullptr;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Tegra::Engines::Upload
 | 
					} // namespace Tegra::Engines::Upload
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ KeplerCompute::~KeplerCompute() = default;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
 | 
					void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
 | 
				
			||||||
    rasterizer = rasterizer_;
 | 
					    rasterizer = rasterizer_;
 | 
				
			||||||
 | 
					    upload_state.BindRasterizer(rasterizer);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
 | 
					void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,10 @@ KeplerMemory::KeplerMemory(Core::System& system_, MemoryManager& memory_manager)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
KeplerMemory::~KeplerMemory() = default;
 | 
					KeplerMemory::~KeplerMemory() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void KeplerMemory::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
 | 
				
			||||||
 | 
					    upload_state.BindRasterizer(rasterizer_);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void KeplerMemory::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
 | 
					void KeplerMemory::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
 | 
				
			||||||
    ASSERT_MSG(method < Regs::NUM_REGS,
 | 
					    ASSERT_MSG(method < Regs::NUM_REGS,
 | 
				
			||||||
               "Invalid KeplerMemory register, increase the size of the Regs structure");
 | 
					               "Invalid KeplerMemory register, increase the size of the Regs structure");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,10 @@ namespace Tegra {
 | 
				
			|||||||
class MemoryManager;
 | 
					class MemoryManager;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace VideoCore {
 | 
				
			||||||
 | 
					class RasterizerInterface;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Tegra::Engines {
 | 
					namespace Tegra::Engines {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -38,6 +42,9 @@ public:
 | 
				
			|||||||
    explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager);
 | 
					    explicit KeplerMemory(Core::System& system_, MemoryManager& memory_manager);
 | 
				
			||||||
    ~KeplerMemory() override;
 | 
					    ~KeplerMemory() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Binds a rasterizer to this engine.
 | 
				
			||||||
 | 
					    void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Write the value to the register identified by method.
 | 
					    /// Write the value to the register identified by method.
 | 
				
			||||||
    void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
 | 
					    void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,7 @@ Maxwell3D::~Maxwell3D() = default;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
 | 
					void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
 | 
				
			||||||
    rasterizer = rasterizer_;
 | 
					    rasterizer = rasterizer_;
 | 
				
			||||||
 | 
					    upload_state.BindRasterizer(rasterizer_);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Maxwell3D::InitializeRegisterDefaults() {
 | 
					void Maxwell3D::InitializeRegisterDefaults() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1557,7 +1557,8 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    static constexpr u32 null_cb_data = 0xFFFFFFFF;
 | 
					    static constexpr u32 null_cb_data = 0xFFFFFFFF;
 | 
				
			||||||
    struct CBDataState {
 | 
					    struct CBDataState {
 | 
				
			||||||
        std::array<std::array<u32, 0x4000>, 16> buffer;
 | 
					        static constexpr size_t inline_size = 0x4000;
 | 
				
			||||||
 | 
					        std::array<std::array<u32, inline_size>, 16> buffer;
 | 
				
			||||||
        u32 current{null_cb_data};
 | 
					        u32 current{null_cb_data};
 | 
				
			||||||
        u32 id{null_cb_data};
 | 
					        u32 id{null_cb_data};
 | 
				
			||||||
        u32 start_pos{};
 | 
					        u32 start_pos{};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,6 +59,7 @@ struct GPU::Impl {
 | 
				
			|||||||
        maxwell_3d->BindRasterizer(rasterizer);
 | 
					        maxwell_3d->BindRasterizer(rasterizer);
 | 
				
			||||||
        fermi_2d->BindRasterizer(rasterizer);
 | 
					        fermi_2d->BindRasterizer(rasterizer);
 | 
				
			||||||
        kepler_compute->BindRasterizer(rasterizer);
 | 
					        kepler_compute->BindRasterizer(rasterizer);
 | 
				
			||||||
 | 
					        kepler_memory->BindRasterizer(rasterizer);
 | 
				
			||||||
        maxwell_dma->BindRasterizer(rasterizer);
 | 
					        maxwell_dma->BindRasterizer(rasterizer);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -502,8 +503,13 @@ struct GPU::Impl {
 | 
				
			|||||||
        case BufferMethods::SemaphoreAddressHigh:
 | 
					        case BufferMethods::SemaphoreAddressHigh:
 | 
				
			||||||
        case BufferMethods::SemaphoreAddressLow:
 | 
					        case BufferMethods::SemaphoreAddressLow:
 | 
				
			||||||
        case BufferMethods::SemaphoreSequence:
 | 
					        case BufferMethods::SemaphoreSequence:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        case BufferMethods::UnkCacheFlush:
 | 
					        case BufferMethods::UnkCacheFlush:
 | 
				
			||||||
 | 
					            rasterizer->SyncGuestHost();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        case BufferMethods::WrcacheFlush:
 | 
					        case BufferMethods::WrcacheFlush:
 | 
				
			||||||
 | 
					            rasterizer->SignalReference();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        case BufferMethods::FenceValue:
 | 
					        case BufferMethods::FenceValue:
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case BufferMethods::RefCnt:
 | 
					        case BufferMethods::RefCnt:
 | 
				
			||||||
@@ -513,7 +519,7 @@ struct GPU::Impl {
 | 
				
			|||||||
            ProcessFenceActionMethod();
 | 
					            ProcessFenceActionMethod();
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case BufferMethods::WaitForInterrupt:
 | 
					        case BufferMethods::WaitForInterrupt:
 | 
				
			||||||
            ProcessWaitForInterruptMethod();
 | 
					            rasterizer->WaitForIdle();
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case BufferMethods::SemaphoreTrigger: {
 | 
					        case BufferMethods::SemaphoreTrigger: {
 | 
				
			||||||
            ProcessSemaphoreTriggerMethod();
 | 
					            ProcessSemaphoreTriggerMethod();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -143,6 +143,8 @@ public:
 | 
				
			|||||||
    [[nodiscard]] GPUVAddr Allocate(std::size_t size, std::size_t align);
 | 
					    [[nodiscard]] GPUVAddr Allocate(std::size_t size, std::size_t align);
 | 
				
			||||||
    void Unmap(GPUVAddr gpu_addr, std::size_t size);
 | 
					    void Unmap(GPUVAddr gpu_addr, std::size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void FlushRegion(GPUVAddr gpu_addr, size_t size) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    [[nodiscard]] PageEntry GetPageEntry(GPUVAddr gpu_addr) const;
 | 
					    [[nodiscard]] PageEntry GetPageEntry(GPUVAddr gpu_addr) const;
 | 
				
			||||||
    void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size);
 | 
					    void SetPageEntry(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size = page_size);
 | 
				
			||||||
@@ -153,8 +155,6 @@ private:
 | 
				
			|||||||
    void TryLockPage(PageEntry page_entry, std::size_t size);
 | 
					    void TryLockPage(PageEntry page_entry, std::size_t size);
 | 
				
			||||||
    void TryUnlockPage(PageEntry page_entry, std::size_t size);
 | 
					    void TryUnlockPage(PageEntry page_entry, std::size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void FlushRegion(GPUVAddr gpu_addr, size_t size) const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void ReadBlockImpl(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size,
 | 
					    void ReadBlockImpl(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size,
 | 
				
			||||||
                       bool is_safe) const;
 | 
					                       bool is_safe) const;
 | 
				
			||||||
    void WriteBlockImpl(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size,
 | 
					    void WriteBlockImpl(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -123,6 +123,9 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    [[nodiscard]] virtual Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() = 0;
 | 
					    [[nodiscard]] virtual Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
 | 
				
			||||||
 | 
					                                          std::span<u8> memory) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Attempt to use a faster method to display the framebuffer to screen
 | 
					    /// Attempt to use a faster method to display the framebuffer to screen
 | 
				
			||||||
    [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config,
 | 
					    [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config,
 | 
				
			||||||
                                                 VAddr framebuffer_addr, u32 pixel_stride) {
 | 
					                                                 VAddr framebuffer_addr, u32 pixel_stride) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -484,6 +484,28 @@ Tegra::Engines::AccelerateDMAInterface& RasterizerOpenGL::AccessAccelerateDMA()
 | 
				
			|||||||
    return accelerate_dma;
 | 
					    return accelerate_dma;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
 | 
				
			||||||
 | 
					                                                std::span<u8> memory) {
 | 
				
			||||||
 | 
					    auto cpu_addr = gpu_memory.GpuToCpuAddress(address);
 | 
				
			||||||
 | 
					    if (!cpu_addr) [[unlikely]] {
 | 
				
			||||||
 | 
					        gpu_memory.WriteBlock(address, memory.data(), copy_size);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    gpu_memory.WriteBlockUnsafe(address, memory.data(), copy_size);
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::unique_lock<std::mutex> lock{buffer_cache.mutex};
 | 
				
			||||||
 | 
					        if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) {
 | 
				
			||||||
 | 
					            buffer_cache.WriteMemory(*cpu_addr, copy_size);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::scoped_lock lock_texture{texture_cache.mutex};
 | 
				
			||||||
 | 
					        texture_cache.WriteMemory(*cpu_addr, copy_size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    shader_cache.InvalidateRegion(*cpu_addr, copy_size);
 | 
				
			||||||
 | 
					    query_cache.InvalidateRegion(*cpu_addr, copy_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
 | 
					bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
 | 
				
			||||||
                                         VAddr framebuffer_addr, u32 pixel_stride) {
 | 
					                                         VAddr framebuffer_addr, u32 pixel_stride) {
 | 
				
			||||||
    if (framebuffer_addr == 0) {
 | 
					    if (framebuffer_addr == 0) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,6 +106,8 @@ public:
 | 
				
			|||||||
                               const Tegra::Engines::Fermi2D::Surface& dst,
 | 
					                               const Tegra::Engines::Fermi2D::Surface& dst,
 | 
				
			||||||
                               const Tegra::Engines::Fermi2D::Config& copy_config) override;
 | 
					                               const Tegra::Engines::Fermi2D::Config& copy_config) override;
 | 
				
			||||||
    Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
 | 
					    Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
 | 
				
			||||||
 | 
					    void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
 | 
				
			||||||
 | 
					                                  std::span<u8> memory) override;
 | 
				
			||||||
    bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
 | 
					    bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
 | 
				
			||||||
                           u32 pixel_stride) override;
 | 
					                           u32 pixel_stride) override;
 | 
				
			||||||
    void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
 | 
					    void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -548,6 +548,28 @@ Tegra::Engines::AccelerateDMAInterface& RasterizerVulkan::AccessAccelerateDMA()
 | 
				
			|||||||
    return accelerate_dma;
 | 
					    return accelerate_dma;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
 | 
				
			||||||
 | 
					                                                std::span<u8> memory) {
 | 
				
			||||||
 | 
					    auto cpu_addr = gpu_memory.GpuToCpuAddress(address);
 | 
				
			||||||
 | 
					    if (!cpu_addr) [[unlikely]] {
 | 
				
			||||||
 | 
					        gpu_memory.WriteBlock(address, memory.data(), copy_size);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    gpu_memory.WriteBlockUnsafe(address, memory.data(), copy_size);
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::unique_lock<std::mutex> lock{buffer_cache.mutex};
 | 
				
			||||||
 | 
					        if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) {
 | 
				
			||||||
 | 
					            buffer_cache.WriteMemory(*cpu_addr, copy_size);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::scoped_lock lock_texture{texture_cache.mutex};
 | 
				
			||||||
 | 
					        texture_cache.WriteMemory(*cpu_addr, copy_size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pipeline_cache.InvalidateRegion(*cpu_addr, copy_size);
 | 
				
			||||||
 | 
					    query_cache.InvalidateRegion(*cpu_addr, copy_size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
 | 
					bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
 | 
				
			||||||
                                         VAddr framebuffer_addr, u32 pixel_stride) {
 | 
					                                         VAddr framebuffer_addr, u32 pixel_stride) {
 | 
				
			||||||
    if (!framebuffer_addr) {
 | 
					    if (!framebuffer_addr) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -99,6 +99,8 @@ public:
 | 
				
			|||||||
                               const Tegra::Engines::Fermi2D::Surface& dst,
 | 
					                               const Tegra::Engines::Fermi2D::Surface& dst,
 | 
				
			||||||
                               const Tegra::Engines::Fermi2D::Config& copy_config) override;
 | 
					                               const Tegra::Engines::Fermi2D::Config& copy_config) override;
 | 
				
			||||||
    Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
 | 
					    Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
 | 
				
			||||||
 | 
					    void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
 | 
				
			||||||
 | 
					                                  std::span<u8> memory) override;
 | 
				
			||||||
    bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
 | 
					    bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
 | 
				
			||||||
                           u32 pixel_stride) override;
 | 
					                           u32 pixel_stride) override;
 | 
				
			||||||
    void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
 | 
					    void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user