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
|
debug_utils/debug_utils.h
|
||||||
engines/fermi_2d.cpp
|
engines/fermi_2d.cpp
|
||||||
engines/fermi_2d.h
|
engines/fermi_2d.h
|
||||||
|
engines/kepler_memory.cpp
|
||||||
|
engines/kepler_memory.h
|
||||||
engines/maxwell_3d.cpp
|
engines/maxwell_3d.cpp
|
||||||
engines/maxwell_3d.h
|
engines/maxwell_3d.h
|
||||||
engines/maxwell_compute.cpp
|
engines/maxwell_compute.cpp
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "core/tracer/recorder.h"
|
#include "core/tracer/recorder.h"
|
||||||
#include "video_core/command_processor.h"
|
#include "video_core/command_processor.h"
|
||||||
#include "video_core/engines/fermi_2d.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_3d.h"
|
||||||
#include "video_core/engines/maxwell_compute.h"
|
#include "video_core/engines/maxwell_compute.h"
|
||||||
#include "video_core/engines/maxwell_dma.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:
|
case EngineID::MAXWELL_DMA_COPY_A:
|
||||||
maxwell_dma->WriteReg(method, value);
|
maxwell_dma->WriteReg(method, value);
|
||||||
break;
|
break;
|
||||||
|
case EngineID::KEPLER_INLINE_TO_MEMORY_B:
|
||||||
|
kepler_memory->WriteReg(method, value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_MSG("Unimplemented engine");
|
UNIMPLEMENTED_MSG("Unimplemented engine");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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 "common/assert.h"
|
||||||
#include "video_core/engines/fermi_2d.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_3d.h"
|
||||||
#include "video_core/engines/maxwell_compute.h"
|
#include "video_core/engines/maxwell_compute.h"
|
||||||
#include "video_core/engines/maxwell_dma.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);
|
fermi_2d = std::make_unique<Engines::Fermi2D>(*memory_manager);
|
||||||
maxwell_compute = std::make_unique<Engines::MaxwellCompute>();
|
maxwell_compute = std::make_unique<Engines::MaxwellCompute>();
|
||||||
maxwell_dma = std::make_unique<Engines::MaxwellDMA>(*memory_manager);
|
maxwell_dma = std::make_unique<Engines::MaxwellDMA>(*memory_manager);
|
||||||
|
kepler_memory = std::make_unique<Engines::KeplerMemory>(*memory_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPU::~GPU() = default;
|
GPU::~GPU() = default;
|
||||||
|
|
|
@ -102,6 +102,7 @@ class Fermi2D;
|
||||||
class Maxwell3D;
|
class Maxwell3D;
|
||||||
class MaxwellCompute;
|
class MaxwellCompute;
|
||||||
class MaxwellDMA;
|
class MaxwellDMA;
|
||||||
|
class KeplerMemory;
|
||||||
} // namespace Engines
|
} // namespace Engines
|
||||||
|
|
||||||
enum class EngineID {
|
enum class EngineID {
|
||||||
|
@ -146,6 +147,8 @@ private:
|
||||||
std::unique_ptr<Engines::MaxwellCompute> maxwell_compute;
|
std::unique_ptr<Engines::MaxwellCompute> maxwell_compute;
|
||||||
/// DMA engine
|
/// DMA engine
|
||||||
std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
|
std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
|
||||||
|
/// Inline memory engine
|
||||||
|
std::unique_ptr<Engines::KeplerMemory> kepler_memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Tegra
|
} // namespace Tegra
|
||||||
|
|
Reference in New Issue