diff options
| -rw-r--r-- | src/video_core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 57 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 19 | ||||
| -rw-r--r-- | src/video_core/gpu.cpp | 21 | ||||
| -rw-r--r-- | src/video_core/gpu.h | 18 |
5 files changed, 105 insertions, 11 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index ed87f8ff1..2f946e7be 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -7,6 +7,7 @@ add_library(video_core STATIC | |||
| 7 | engines/maxwell_3d.h | 7 | engines/maxwell_3d.h |
| 8 | engines/maxwell_compute.cpp | 8 | engines/maxwell_compute.cpp |
| 9 | engines/maxwell_compute.h | 9 | engines/maxwell_compute.h |
| 10 | gpu.cpp | ||
| 10 | gpu.h | 11 | gpu.h |
| 11 | memory_manager.cpp | 12 | memory_manager.cpp |
| 12 | memory_manager.h | 13 | memory_manager.h |
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 49a138c1d..3a4e88e4e 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -13,6 +13,7 @@ constexpr u32 MacroRegistersStart = 0xE00; | |||
| 13 | 13 | ||
| 14 | const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers = { | 14 | const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers = { |
| 15 | {0xE24, {"SetShader", 5, &Maxwell3D::SetShader}}, | 15 | {0xE24, {"SetShader", 5, &Maxwell3D::SetShader}}, |
| 16 | {0xE2A, {"BindStorageBuffer", 1, &Maxwell3D::BindStorageBuffer}}, | ||
| 16 | }; | 17 | }; |
| 17 | 18 | ||
| 18 | Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} | 19 | Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} |
| @@ -83,6 +84,25 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { | |||
| 83 | ASSERT_MSG(regs.code_address.CodeAddress() == 0, "Unexpected CODE_ADDRESS register value."); | 84 | ASSERT_MSG(regs.code_address.CodeAddress() == 0, "Unexpected CODE_ADDRESS register value."); |
| 84 | break; | 85 | break; |
| 85 | } | 86 | } |
| 87 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]): | ||
| 88 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]): | ||
| 89 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]): | ||
| 90 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[3]): | ||
| 91 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[4]): | ||
| 92 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[5]): | ||
| 93 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[6]): | ||
| 94 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[7]): | ||
| 95 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[8]): | ||
| 96 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[9]): | ||
| 97 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[10]): | ||
| 98 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[11]): | ||
| 99 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]): | ||
| 100 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]): | ||
| 101 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]): | ||
| 102 | case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): { | ||
| 103 | ProcessCBData(value); | ||
| 104 | break; | ||
| 105 | } | ||
| 86 | case MAXWELL3D_REG_INDEX(cb_bind[0].raw_config): { | 106 | case MAXWELL3D_REG_INDEX(cb_bind[0].raw_config): { |
| 87 | ProcessCBBind(Regs::ShaderStage::Vertex); | 107 | ProcessCBBind(Regs::ShaderStage::Vertex); |
| 88 | break; | 108 | break; |
| @@ -181,6 +201,26 @@ void Maxwell3D::SetShader(const std::vector<u32>& parameters) { | |||
| 181 | ProcessCBBind(shader_stage); | 201 | ProcessCBBind(shader_stage); |
| 182 | } | 202 | } |
| 183 | 203 | ||
| 204 | void Maxwell3D::BindStorageBuffer(const std::vector<u32>& parameters) { | ||
| 205 | /** | ||
| 206 | * Parameters description: | ||
| 207 | * [0] = Buffer offset >> 2 | ||
| 208 | */ | ||
| 209 | |||
| 210 | u32 buffer_offset = parameters[0] << 2; | ||
| 211 | |||
| 212 | // Perform the same operations as the real macro code. | ||
| 213 | // Note: This value is hardcoded in the macro's code. | ||
| 214 | static constexpr u32 DefaultCBSize = 0x5F00; | ||
| 215 | regs.const_buffer.cb_size = DefaultCBSize; | ||
| 216 | |||
| 217 | GPUVAddr address = regs.ssbo_info.BufferAddress(); | ||
| 218 | regs.const_buffer.cb_address_high = address >> 32; | ||
| 219 | regs.const_buffer.cb_address_low = address & 0xFFFFFFFF; | ||
| 220 | |||
| 221 | regs.const_buffer.cb_pos = buffer_offset; | ||
| 222 | } | ||
| 223 | |||
| 184 | void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { | 224 | void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { |
| 185 | // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage. | 225 | // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage. |
| 186 | auto& shader = state.shader_stages[static_cast<size_t>(stage)]; | 226 | auto& shader = state.shader_stages[static_cast<size_t>(stage)]; |
| @@ -194,5 +234,22 @@ void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { | |||
| 194 | buffer.size = regs.const_buffer.cb_size; | 234 | buffer.size = regs.const_buffer.cb_size; |
| 195 | } | 235 | } |
| 196 | 236 | ||
| 237 | void Maxwell3D::ProcessCBData(u32 value) { | ||
| 238 | // Write the input value to the current const buffer at the current position. | ||
| 239 | GPUVAddr buffer_address = regs.const_buffer.BufferAddress(); | ||
| 240 | ASSERT(buffer_address != 0); | ||
| 241 | |||
| 242 | // Don't allow writing past the end of the buffer. | ||
| 243 | ASSERT(regs.const_buffer.cb_pos + sizeof(u32) <= regs.const_buffer.cb_size); | ||
| 244 | |||
| 245 | VAddr address = | ||
| 246 | memory_manager.PhysicalToVirtualAddress(buffer_address + regs.const_buffer.cb_pos); | ||
| 247 | |||
| 248 | Memory::Write32(address, value); | ||
| 249 | |||
| 250 | // Increment the current buffer position. | ||
| 251 | regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4; | ||
| 252 | } | ||
| 253 | |||
| 197 | } // namespace Engines | 254 | } // namespace Engines |
| 198 | } // namespace Tegra | 255 | } // namespace Tegra |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 05820a21e..3e97d9045 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -166,7 +166,19 @@ public: | |||
| 166 | 166 | ||
| 167 | u32 tex_cb_index; | 167 | u32 tex_cb_index; |
| 168 | 168 | ||
| 169 | INSERT_PADDING_WORDS(0x4B3); | 169 | INSERT_PADDING_WORDS(0x395); |
| 170 | |||
| 171 | struct { | ||
| 172 | /// Compressed address of a buffer that holds information about bound SSBOs. | ||
| 173 | /// This address is usually bound to c0 in the shaders. | ||
| 174 | u32 buffer_address; | ||
| 175 | |||
| 176 | GPUVAddr BufferAddress() const { | ||
| 177 | return static_cast<GPUVAddr>(buffer_address) << 8; | ||
| 178 | } | ||
| 179 | } ssbo_info; | ||
| 180 | |||
| 181 | INSERT_PADDING_WORDS(0x11D); | ||
| 170 | }; | 182 | }; |
| 171 | std::array<u32, NUM_REGS> reg_array; | 183 | std::array<u32, NUM_REGS> reg_array; |
| 172 | }; | 184 | }; |
| @@ -218,6 +230,9 @@ private: | |||
| 218 | /// Handles a write to the QUERY_GET register. | 230 | /// Handles a write to the QUERY_GET register. |
| 219 | void ProcessQueryGet(); | 231 | void ProcessQueryGet(); |
| 220 | 232 | ||
| 233 | /// Handles a write to the CB_DATA[i] register. | ||
| 234 | void ProcessCBData(u32 value); | ||
| 235 | |||
| 221 | /// Handles a write to the CB_BIND register. | 236 | /// Handles a write to the CB_BIND register. |
| 222 | void ProcessCBBind(Regs::ShaderStage stage); | 237 | void ProcessCBBind(Regs::ShaderStage stage); |
| 223 | 238 | ||
| @@ -226,6 +241,7 @@ private: | |||
| 226 | 241 | ||
| 227 | /// Method call handlers | 242 | /// Method call handlers |
| 228 | void SetShader(const std::vector<u32>& parameters); | 243 | void SetShader(const std::vector<u32>& parameters); |
| 244 | void BindStorageBuffer(const std::vector<u32>& parameters); | ||
| 229 | 245 | ||
| 230 | struct MethodInfo { | 246 | struct MethodInfo { |
| 231 | const char* name; | 247 | const char* name; |
| @@ -249,6 +265,7 @@ ASSERT_REG_POSITION(shader_config[0], 0x800); | |||
| 249 | ASSERT_REG_POSITION(const_buffer, 0x8E0); | 265 | ASSERT_REG_POSITION(const_buffer, 0x8E0); |
| 250 | ASSERT_REG_POSITION(cb_bind[0], 0x904); | 266 | ASSERT_REG_POSITION(cb_bind[0], 0x904); |
| 251 | ASSERT_REG_POSITION(tex_cb_index, 0x982); | 267 | ASSERT_REG_POSITION(tex_cb_index, 0x982); |
| 268 | ASSERT_REG_POSITION(ssbo_info, 0xD18); | ||
| 252 | 269 | ||
| 253 | #undef ASSERT_REG_POSITION | 270 | #undef ASSERT_REG_POSITION |
| 254 | 271 | ||
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp new file mode 100644 index 000000000..c384d236e --- /dev/null +++ b/src/video_core/gpu.cpp | |||
| @@ -0,0 +1,21 @@ | |||
| 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 "video_core/engines/fermi_2d.h" | ||
| 6 | #include "video_core/engines/maxwell_3d.h" | ||
| 7 | #include "video_core/engines/maxwell_compute.h" | ||
| 8 | #include "video_core/gpu.h" | ||
| 9 | |||
| 10 | namespace Tegra { | ||
| 11 | |||
| 12 | GPU::GPU() { | ||
| 13 | memory_manager = std::make_unique<MemoryManager>(); | ||
| 14 | maxwell_3d = std::make_unique<Engines::Maxwell3D>(*memory_manager); | ||
| 15 | fermi_2d = std::make_unique<Engines::Fermi2D>(); | ||
| 16 | maxwell_compute = std::make_unique<Engines::MaxwellCompute>(); | ||
| 17 | } | ||
| 18 | |||
| 19 | GPU::~GPU() = default; | ||
| 20 | |||
| 21 | } // namespace Tegra | ||
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index d2e4ff52d..2a9064ba3 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -8,13 +8,16 @@ | |||
| 8 | #include <unordered_map> | 8 | #include <unordered_map> |
| 9 | #include <vector> | 9 | #include <vector> |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "video_core/engines/fermi_2d.h" | ||
| 12 | #include "video_core/engines/maxwell_3d.h" | ||
| 13 | #include "video_core/engines/maxwell_compute.h" | ||
| 14 | #include "video_core/memory_manager.h" | 11 | #include "video_core/memory_manager.h" |
| 15 | 12 | ||
| 16 | namespace Tegra { | 13 | namespace Tegra { |
| 17 | 14 | ||
| 15 | namespace Engines { | ||
| 16 | class Fermi2D; | ||
| 17 | class Maxwell3D; | ||
| 18 | class MaxwellCompute; | ||
| 19 | } // namespace Engines | ||
| 20 | |||
| 18 | enum class EngineID { | 21 | enum class EngineID { |
| 19 | FERMI_TWOD_A = 0x902D, // 2D Engine | 22 | FERMI_TWOD_A = 0x902D, // 2D Engine |
| 20 | MAXWELL_B = 0xB197, // 3D Engine | 23 | MAXWELL_B = 0xB197, // 3D Engine |
| @@ -25,13 +28,8 @@ enum class EngineID { | |||
| 25 | 28 | ||
| 26 | class GPU final { | 29 | class GPU final { |
| 27 | public: | 30 | public: |
| 28 | GPU() { | 31 | GPU(); |
| 29 | memory_manager = std::make_unique<MemoryManager>(); | 32 | ~GPU(); |
| 30 | maxwell_3d = std::make_unique<Engines::Maxwell3D>(*memory_manager); | ||
| 31 | fermi_2d = std::make_unique<Engines::Fermi2D>(); | ||
| 32 | maxwell_compute = std::make_unique<Engines::MaxwellCompute>(); | ||
| 33 | } | ||
| 34 | ~GPU() = default; | ||
| 35 | 33 | ||
| 36 | /// Processes a command list stored at the specified address in GPU memory. | 34 | /// Processes a command list stored at the specified address in GPU memory. |
| 37 | void ProcessCommandList(GPUVAddr address, u32 size); | 35 | void ProcessCommandList(GPUVAddr address, u32 size); |