summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2018-03-19 00:45:40 +0100
committerGitHub <noreply@github.com>2018-03-19 00:45:40 +0100
commit6317a0b2ca5cfd5997d60522554d6f1f6b94a979 (patch)
treed86384f4fed07fc791541e49b8ef0f7834461c35
parentMerge pull request #246 from Subv/gpu_macro_calls (diff)
parentGPU: Implement the BindStorageBuffer macro method in HLE. (diff)
downloadyuzu-6317a0b2ca5cfd5997d60522554d6f1f6b94a979.tar
yuzu-6317a0b2ca5cfd5997d60522554d6f1f6b94a979.tar.gz
yuzu-6317a0b2ca5cfd5997d60522554d6f1f6b94a979.tar.bz2
yuzu-6317a0b2ca5cfd5997d60522554d6f1f6b94a979.tar.lz
yuzu-6317a0b2ca5cfd5997d60522554d6f1f6b94a979.tar.xz
yuzu-6317a0b2ca5cfd5997d60522554d6f1f6b94a979.tar.zst
yuzu-6317a0b2ca5cfd5997d60522554d6f1f6b94a979.zip
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/engines/maxwell_3d.cpp57
-rw-r--r--src/video_core/engines/maxwell_3d.h19
-rw-r--r--src/video_core/gpu.cpp21
-rw-r--r--src/video_core/gpu.h18
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
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/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;
const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers = {
{0xE24, {"SetShader", 5, &Maxwell3D::SetShader}},
+ {0xE2A, {"BindStorageBuffer", 1, &Maxwell3D::BindStorageBuffer}},
};
Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {}
@@ -83,6 +84,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;
@@ -181,6 +201,26 @@ void Maxwell3D::SetShader(const std::vector<u32>& parameters) {
ProcessCBBind(shader_stage);
}
+void Maxwell3D::BindStorageBuffer(const std::vector<u32>& 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<size_t>(stage)];
@@ -194,5 +234,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..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<GPUVAddr>(buffer_address) << 8;
+ }
+ } ssbo_info;
+
+ INSERT_PADDING_WORDS(0x11D);
};
std::array<u32, NUM_REGS> reg_array;
};
@@ -218,6 +230,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);
@@ -226,6 +241,7 @@ private:
/// Method call handlers
void SetShader(const std::vector<u32>& parameters);
+ void BindStorageBuffer(const std::vector<u32>& parameters);
struct MethodInfo {
const char* name;
@@ -249,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
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<MemoryManager>();
+ maxwell_3d = std::make_unique<Engines::Maxwell3D>(*memory_manager);
+ fermi_2d = std::make_unique<Engines::Fermi2D>();
+ maxwell_compute = std::make_unique<Engines::MaxwellCompute>();
+}
+
+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 <unordered_map>
#include <vector>
#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<MemoryManager>();
- maxwell_3d = std::make_unique<Engines::Maxwell3D>(*memory_manager);
- fermi_2d = std::make_unique<Engines::Fermi2D>();
- maxwell_compute = std::make_unique<Engines::MaxwellCompute>();
- }
- ~GPU() = default;
+ GPU();
+ ~GPU();
/// Processes a command list stored at the specified address in GPU memory.
void ProcessCommandList(GPUVAddr address, u32 size);