mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	GPU: Basic implementation of the Kepler Inline Memory engine (p2mf).
This engine writes data from a FIFO register into the configured address.
This commit is contained in:
		
							parent
							
								
									79217f9870
								
							
						
					
					
						commit
						bb5eb4f20a
					
				@ -5,6 +5,8 @@ add_library(video_core STATIC
 | 
			
		||||
    debug_utils/debug_utils.h
 | 
			
		||||
    engines/fermi_2d.cpp
 | 
			
		||||
    engines/fermi_2d.h
 | 
			
		||||
    engines/kepler_memory.cpp
 | 
			
		||||
    engines/kepler_memory.h
 | 
			
		||||
    engines/maxwell_3d.cpp
 | 
			
		||||
    engines/maxwell_3d.h
 | 
			
		||||
    engines/maxwell_compute.cpp
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@
 | 
			
		||||
#include "core/tracer/recorder.h"
 | 
			
		||||
#include "video_core/command_processor.h"
 | 
			
		||||
#include "video_core/engines/fermi_2d.h"
 | 
			
		||||
#include "video_core/engines/kepler_memory.h"
 | 
			
		||||
#include "video_core/engines/maxwell_3d.h"
 | 
			
		||||
#include "video_core/engines/maxwell_compute.h"
 | 
			
		||||
#include "video_core/engines/maxwell_dma.h"
 | 
			
		||||
@ -69,6 +70,9 @@ void GPU::ProcessCommandLists(const std::vector<CommandListHeader>& commands) {
 | 
			
		||||
        case EngineID::MAXWELL_DMA_COPY_A:
 | 
			
		||||
            maxwell_dma->WriteReg(method, value);
 | 
			
		||||
            break;
 | 
			
		||||
        case EngineID::KEPLER_INLINE_TO_MEMORY_B:
 | 
			
		||||
            kepler_memory->WriteReg(method, value);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            UNIMPLEMENTED_MSG("Unimplemented engine");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								src/video_core/engines/kepler_memory.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/video_core/engines/kepler_memory.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
// Copyright 2018 yuzu Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "core/memory.h"
 | 
			
		||||
#include "video_core/engines/kepler_memory.h"
 | 
			
		||||
 | 
			
		||||
namespace Tegra::Engines {
 | 
			
		||||
 | 
			
		||||
KeplerMemory::KeplerMemory(MemoryManager& memory_manager) : memory_manager(memory_manager) {}
 | 
			
		||||
KeplerMemory::~KeplerMemory() = default;
 | 
			
		||||
 | 
			
		||||
void KeplerMemory::WriteReg(u32 method, u32 value) {
 | 
			
		||||
    ASSERT_MSG(method < Regs::NUM_REGS,
 | 
			
		||||
               "Invalid KeplerMemory register, increase the size of the Regs structure");
 | 
			
		||||
 | 
			
		||||
    regs.reg_array[method] = value;
 | 
			
		||||
 | 
			
		||||
    switch (method) {
 | 
			
		||||
    case KEPLERMEMORY_REG_INDEX(exec): {
 | 
			
		||||
        state.write_offset = 0;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case KEPLERMEMORY_REG_INDEX(data): {
 | 
			
		||||
        ProcessData(value);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KeplerMemory::ProcessData(u32 data) {
 | 
			
		||||
    ASSERT_MSG(regs.exec.linear, "Non-linear uploads are not supported");
 | 
			
		||||
    ASSERT(regs.dest.x == 0 && regs.dest.y == 0 && regs.dest.z == 0);
 | 
			
		||||
 | 
			
		||||
    GPUVAddr address = regs.dest.Address();
 | 
			
		||||
    VAddr dest_address =
 | 
			
		||||
        *memory_manager.GpuToCpuAddress(address + state.write_offset * sizeof(u32));
 | 
			
		||||
 | 
			
		||||
    Memory::Write32(dest_address, data);
 | 
			
		||||
 | 
			
		||||
    state.write_offset++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Tegra::Engines
 | 
			
		||||
							
								
								
									
										90
									
								
								src/video_core/engines/kepler_memory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/video_core/engines/kepler_memory.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
			
		||||
// Copyright 2018 yuzu Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
#include "common/common_funcs.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "video_core/memory_manager.h"
 | 
			
		||||
 | 
			
		||||
namespace Tegra::Engines {
 | 
			
		||||
 | 
			
		||||
#define KEPLERMEMORY_REG_INDEX(field_name)                                                         \
 | 
			
		||||
    (offsetof(Tegra::Engines::KeplerMemory::Regs, field_name) / sizeof(u32))
 | 
			
		||||
 | 
			
		||||
class KeplerMemory final {
 | 
			
		||||
public:
 | 
			
		||||
    KeplerMemory(MemoryManager& memory_manager);
 | 
			
		||||
    ~KeplerMemory();
 | 
			
		||||
 | 
			
		||||
    /// Write the value to the register identified by method.
 | 
			
		||||
    void WriteReg(u32 method, u32 value);
 | 
			
		||||
 | 
			
		||||
    struct Regs {
 | 
			
		||||
        static constexpr size_t NUM_REGS = 0x7F;
 | 
			
		||||
 | 
			
		||||
        union {
 | 
			
		||||
            struct {
 | 
			
		||||
                INSERT_PADDING_WORDS(0x60);
 | 
			
		||||
 | 
			
		||||
                u32 line_length_in;
 | 
			
		||||
                u32 line_count;
 | 
			
		||||
 | 
			
		||||
                struct {
 | 
			
		||||
                    u32 address_high;
 | 
			
		||||
                    u32 address_low;
 | 
			
		||||
                    u32 pitch;
 | 
			
		||||
                    u32 block_dimensions;
 | 
			
		||||
                    u32 width;
 | 
			
		||||
                    u32 height;
 | 
			
		||||
                    u32 depth;
 | 
			
		||||
                    u32 z;
 | 
			
		||||
                    u32 x;
 | 
			
		||||
                    u32 y;
 | 
			
		||||
 | 
			
		||||
                    GPUVAddr Address() const {
 | 
			
		||||
                        return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
 | 
			
		||||
                                                     address_low);
 | 
			
		||||
                    }
 | 
			
		||||
                } dest;
 | 
			
		||||
 | 
			
		||||
                struct {
 | 
			
		||||
                    union {
 | 
			
		||||
                        BitField<0, 1, u32> linear;
 | 
			
		||||
                    };
 | 
			
		||||
                } exec;
 | 
			
		||||
 | 
			
		||||
                u32 data;
 | 
			
		||||
 | 
			
		||||
                INSERT_PADDING_WORDS(0x11);
 | 
			
		||||
            };
 | 
			
		||||
            std::array<u32, NUM_REGS> reg_array;
 | 
			
		||||
        };
 | 
			
		||||
    } regs{};
 | 
			
		||||
 | 
			
		||||
    struct {
 | 
			
		||||
        u32 write_offset = 0;
 | 
			
		||||
    } state{};
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    MemoryManager& memory_manager;
 | 
			
		||||
 | 
			
		||||
    void ProcessData(u32 data);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define ASSERT_REG_POSITION(field_name, position)                                                  \
 | 
			
		||||
    static_assert(offsetof(KeplerMemory::Regs, field_name) == position * 4,                        \
 | 
			
		||||
                  "Field " #field_name " has invalid position")
 | 
			
		||||
 | 
			
		||||
ASSERT_REG_POSITION(line_length_in, 0x60);
 | 
			
		||||
ASSERT_REG_POSITION(line_count, 0x61);
 | 
			
		||||
ASSERT_REG_POSITION(dest, 0x62);
 | 
			
		||||
ASSERT_REG_POSITION(exec, 0x6C);
 | 
			
		||||
ASSERT_REG_POSITION(data, 0x6D);
 | 
			
		||||
#undef ASSERT_REG_POSITION
 | 
			
		||||
 | 
			
		||||
} // namespace Tegra::Engines
 | 
			
		||||
@ -4,6 +4,7 @@
 | 
			
		||||
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "video_core/engines/fermi_2d.h"
 | 
			
		||||
#include "video_core/engines/kepler_memory.h"
 | 
			
		||||
#include "video_core/engines/maxwell_3d.h"
 | 
			
		||||
#include "video_core/engines/maxwell_compute.h"
 | 
			
		||||
#include "video_core/engines/maxwell_dma.h"
 | 
			
		||||
@ -27,6 +28,7 @@ GPU::GPU(VideoCore::RasterizerInterface& rasterizer) {
 | 
			
		||||
    fermi_2d = std::make_unique<Engines::Fermi2D>(*memory_manager);
 | 
			
		||||
    maxwell_compute = std::make_unique<Engines::MaxwellCompute>();
 | 
			
		||||
    maxwell_dma = std::make_unique<Engines::MaxwellDMA>(*memory_manager);
 | 
			
		||||
    kepler_memory = std::make_unique<Engines::KeplerMemory>(*memory_manager);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GPU::~GPU() = default;
 | 
			
		||||
 | 
			
		||||
@ -102,6 +102,7 @@ class Fermi2D;
 | 
			
		||||
class Maxwell3D;
 | 
			
		||||
class MaxwellCompute;
 | 
			
		||||
class MaxwellDMA;
 | 
			
		||||
class KeplerMemory;
 | 
			
		||||
} // namespace Engines
 | 
			
		||||
 | 
			
		||||
enum class EngineID {
 | 
			
		||||
@ -146,6 +147,8 @@ private:
 | 
			
		||||
    std::unique_ptr<Engines::MaxwellCompute> maxwell_compute;
 | 
			
		||||
    /// DMA engine
 | 
			
		||||
    std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
 | 
			
		||||
    /// Inline memory engine
 | 
			
		||||
    std::unique_ptr<Engines::KeplerMemory> kepler_memory;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Tegra
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user