From a64b936cbe6e779627f69ebde85a3055ccd6c2de Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 18 Mar 2018 15:15:05 -0500 Subject: GPU: Move the GPU's class constructor and destructors to a cpp file. This should reduce recompile times when editing the Maxwell3D register structure. --- src/video_core/CMakeLists.txt | 1 + src/video_core/gpu.cpp | 21 +++++++++++++++++++++ src/video_core/gpu.h | 18 ++++++++---------- 3 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 src/video_core/gpu.cpp 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 engines/maxwell_3d.h engines/maxwell_compute.cpp engines/maxwell_compute.h + gpu.cpp gpu.h memory_manager.cpp memory_manager.h 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 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "video_core/engines/fermi_2d.h" +#include "video_core/engines/maxwell_3d.h" +#include "video_core/engines/maxwell_compute.h" +#include "video_core/gpu.h" + +namespace Tegra { + +GPU::GPU() { + memory_manager = std::make_unique(); + maxwell_3d = std::make_unique(*memory_manager); + fermi_2d = std::make_unique(); + maxwell_compute = std::make_unique(); +} + +GPU::~GPU() = default; + +} // 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 @@ #include #include #include "common/common_types.h" -#include "video_core/engines/fermi_2d.h" -#include "video_core/engines/maxwell_3d.h" -#include "video_core/engines/maxwell_compute.h" #include "video_core/memory_manager.h" namespace Tegra { +namespace Engines { +class Fermi2D; +class Maxwell3D; +class MaxwellCompute; +} // namespace Engines + enum class EngineID { FERMI_TWOD_A = 0x902D, // 2D Engine MAXWELL_B = 0xB197, // 3D Engine @@ -25,13 +28,8 @@ enum class EngineID { class GPU final { public: - GPU() { - memory_manager = std::make_unique(); - maxwell_3d = std::make_unique(*memory_manager); - fermi_2d = std::make_unique(); - maxwell_compute = std::make_unique(); - } - ~GPU() = default; + GPU(); + ~GPU(); /// Processes a command list stored at the specified address in GPU memory. void ProcessCommandList(GPUVAddr address, u32 size); -- cgit v1.2.3 From 85d820b1b45396a593e30b7b267ac2001c4f82b7 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 18 Mar 2018 15:19:47 -0500 Subject: GPU: Handle writes to the CB_DATA method. Writing to this method will cause the written value to be stored in the currently-set ConstBuffer plus CB_POS. This method is usually used to upload uniforms or other shader-visible data. --- src/video_core/engines/maxwell_3d.cpp | 36 +++++++++++++++++++++++++++++++++++ src/video_core/engines/maxwell_3d.h | 3 +++ 2 files changed, 39 insertions(+) diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 49a138c1d..9985e0d50 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -83,6 +83,25 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { ASSERT_MSG(regs.code_address.CodeAddress() == 0, "Unexpected CODE_ADDRESS register value."); break; } + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[0]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[1]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[2]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[3]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[4]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[5]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[6]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[7]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[8]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[9]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[10]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[11]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[12]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[13]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[14]): + case MAXWELL3D_REG_INDEX(const_buffer.cb_data[15]): { + ProcessCBData(value); + break; + } case MAXWELL3D_REG_INDEX(cb_bind[0].raw_config): { ProcessCBBind(Regs::ShaderStage::Vertex); break; @@ -194,5 +213,22 @@ void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { buffer.size = regs.const_buffer.cb_size; } +void Maxwell3D::ProcessCBData(u32 value) { + // Write the input value to the current const buffer at the current position. + GPUVAddr buffer_address = regs.const_buffer.BufferAddress(); + ASSERT(buffer_address != 0); + + // Don't allow writing past the end of the buffer. + ASSERT(regs.const_buffer.cb_pos + sizeof(u32) <= regs.const_buffer.cb_size); + + VAddr address = + memory_manager.PhysicalToVirtualAddress(buffer_address + regs.const_buffer.cb_pos); + + Memory::Write32(address, value); + + // Increment the current buffer position. + regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4; +} + } // namespace Engines } // namespace Tegra diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 05820a21e..93b42b53c 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -218,6 +218,9 @@ private: /// Handles a write to the QUERY_GET register. void ProcessQueryGet(); + /// Handles a write to the CB_DATA[i] register. + void ProcessCBData(u32 value); + /// Handles a write to the CB_BIND register. void ProcessCBBind(Regs::ShaderStage stage); -- cgit v1.2.3 From 7b6868e908319b91785712410b481e9112621175 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 18 Mar 2018 15:22:06 -0500 Subject: GPU: Implement the BindStorageBuffer macro method in HLE. This macro binds the SSBO Info Buffer as the current ConstBuffer. This buffer is usually bound to c0 during shader execution. Games seem to use this macro instead of directly writing the address for some reason. --- src/video_core/engines/maxwell_3d.cpp | 21 +++++++++++++++++++++ src/video_core/engines/maxwell_3d.h | 16 +++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 9985e0d50..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; const std::unordered_map Maxwell3D::method_handlers = { {0xE24, {"SetShader", 5, &Maxwell3D::SetShader}}, + {0xE2A, {"BindStorageBuffer", 1, &Maxwell3D::BindStorageBuffer}}, }; Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} @@ -200,6 +201,26 @@ void Maxwell3D::SetShader(const std::vector& parameters) { ProcessCBBind(shader_stage); } +void Maxwell3D::BindStorageBuffer(const std::vector& parameters) { + /** + * Parameters description: + * [0] = Buffer offset >> 2 + */ + + u32 buffer_offset = parameters[0] << 2; + + // Perform the same operations as the real macro code. + // Note: This value is hardcoded in the macro's code. + static constexpr u32 DefaultCBSize = 0x5F00; + regs.const_buffer.cb_size = DefaultCBSize; + + GPUVAddr address = regs.ssbo_info.BufferAddress(); + regs.const_buffer.cb_address_high = address >> 32; + regs.const_buffer.cb_address_low = address & 0xFFFFFFFF; + + regs.const_buffer.cb_pos = buffer_offset; +} + void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage. auto& shader = state.shader_stages[static_cast(stage)]; diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 93b42b53c..3e97d9045 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -166,7 +166,19 @@ public: u32 tex_cb_index; - INSERT_PADDING_WORDS(0x4B3); + INSERT_PADDING_WORDS(0x395); + + struct { + /// Compressed address of a buffer that holds information about bound SSBOs. + /// This address is usually bound to c0 in the shaders. + u32 buffer_address; + + GPUVAddr BufferAddress() const { + return static_cast(buffer_address) << 8; + } + } ssbo_info; + + INSERT_PADDING_WORDS(0x11D); }; std::array reg_array; }; @@ -229,6 +241,7 @@ private: /// Method call handlers void SetShader(const std::vector& parameters); + void BindStorageBuffer(const std::vector& parameters); struct MethodInfo { const char* name; @@ -252,6 +265,7 @@ ASSERT_REG_POSITION(shader_config[0], 0x800); ASSERT_REG_POSITION(const_buffer, 0x8E0); ASSERT_REG_POSITION(cb_bind[0], 0x904); ASSERT_REG_POSITION(tex_cb_index, 0x982); +ASSERT_REG_POSITION(ssbo_info, 0xD18); #undef ASSERT_REG_POSITION -- cgit v1.2.3