summaryrefslogtreecommitdiff
path: root/src/video_core/engines
diff options
context:
space:
mode:
authorGravatar Subv2018-09-08 15:58:20 -0500
committerGravatar Subv2018-09-12 13:57:08 -0500
commitbb5eb4f20ac74e06317ed5b0c98282cde1f9e119 (patch)
treee1b89238165f33c65ff7909eabd846be5f58785c /src/video_core/engines
parentMerge pull request #1303 from lioncash/error (diff)
downloadyuzu-bb5eb4f20ac74e06317ed5b0c98282cde1f9e119.tar.gz
yuzu-bb5eb4f20ac74e06317ed5b0c98282cde1f9e119.tar.xz
yuzu-bb5eb4f20ac74e06317ed5b0c98282cde1f9e119.zip
GPU: Basic implementation of the Kepler Inline Memory engine (p2mf).
This engine writes data from a FIFO register into the configured address.
Diffstat (limited to 'src/video_core/engines')
-rw-r--r--src/video_core/engines/kepler_memory.cpp45
-rw-r--r--src/video_core/engines/kepler_memory.h90
2 files changed, 135 insertions, 0 deletions
diff --git a/src/video_core/engines/kepler_memory.cpp b/src/video_core/engines/kepler_memory.cpp
new file mode 100644
index 000000000..66ae6332d
--- /dev/null
+++ b/src/video_core/engines/kepler_memory.cpp
@@ -0,0 +1,45 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#include "core/memory.h"
7#include "video_core/engines/kepler_memory.h"
8
9namespace Tegra::Engines {
10
11KeplerMemory::KeplerMemory(MemoryManager& memory_manager) : memory_manager(memory_manager) {}
12KeplerMemory::~KeplerMemory() = default;
13
14void KeplerMemory::WriteReg(u32 method, u32 value) {
15 ASSERT_MSG(method < Regs::NUM_REGS,
16 "Invalid KeplerMemory register, increase the size of the Regs structure");
17
18 regs.reg_array[method] = value;
19
20 switch (method) {
21 case KEPLERMEMORY_REG_INDEX(exec): {
22 state.write_offset = 0;
23 break;
24 }
25 case KEPLERMEMORY_REG_INDEX(data): {
26 ProcessData(value);
27 break;
28 }
29 }
30}
31
32void KeplerMemory::ProcessData(u32 data) {
33 ASSERT_MSG(regs.exec.linear, "Non-linear uploads are not supported");
34 ASSERT(regs.dest.x == 0 && regs.dest.y == 0 && regs.dest.z == 0);
35
36 GPUVAddr address = regs.dest.Address();
37 VAddr dest_address =
38 *memory_manager.GpuToCpuAddress(address + state.write_offset * sizeof(u32));
39
40 Memory::Write32(dest_address, data);
41
42 state.write_offset++;
43}
44
45} // namespace Tegra::Engines
diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h
new file mode 100644
index 000000000..b0d0078cf
--- /dev/null
+++ b/src/video_core/engines/kepler_memory.h
@@ -0,0 +1,90 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include "common/assert.h"
9#include "common/bit_field.h"
10#include "common/common_funcs.h"
11#include "common/common_types.h"
12#include "video_core/memory_manager.h"
13
14namespace Tegra::Engines {
15
16#define KEPLERMEMORY_REG_INDEX(field_name) \
17 (offsetof(Tegra::Engines::KeplerMemory::Regs, field_name) / sizeof(u32))
18
19class KeplerMemory final {
20public:
21 KeplerMemory(MemoryManager& memory_manager);
22 ~KeplerMemory();
23
24 /// Write the value to the register identified by method.
25 void WriteReg(u32 method, u32 value);
26
27 struct Regs {
28 static constexpr size_t NUM_REGS = 0x7F;
29
30 union {
31 struct {
32 INSERT_PADDING_WORDS(0x60);
33
34 u32 line_length_in;
35 u32 line_count;
36
37 struct {
38 u32 address_high;
39 u32 address_low;
40 u32 pitch;
41 u32 block_dimensions;
42 u32 width;
43 u32 height;
44 u32 depth;
45 u32 z;
46 u32 x;
47 u32 y;
48
49 GPUVAddr Address() const {
50 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
51 address_low);
52 }
53 } dest;
54
55 struct {
56 union {
57 BitField<0, 1, u32> linear;
58 };
59 } exec;
60
61 u32 data;
62
63 INSERT_PADDING_WORDS(0x11);
64 };
65 std::array<u32, NUM_REGS> reg_array;
66 };
67 } regs{};
68
69 struct {
70 u32 write_offset = 0;
71 } state{};
72
73private:
74 MemoryManager& memory_manager;
75
76 void ProcessData(u32 data);
77};
78
79#define ASSERT_REG_POSITION(field_name, position) \
80 static_assert(offsetof(KeplerMemory::Regs, field_name) == position * 4, \
81 "Field " #field_name " has invalid position")
82
83ASSERT_REG_POSITION(line_length_in, 0x60);
84ASSERT_REG_POSITION(line_count, 0x61);
85ASSERT_REG_POSITION(dest, 0x62);
86ASSERT_REG_POSITION(exec, 0x6C);
87ASSERT_REG_POSITION(data, 0x6D);
88#undef ASSERT_REG_POSITION
89
90} // namespace Tegra::Engines