yuzu-emu
/
yuzu-mainline
Archived
1
0
Fork 0

Merge pull request #248 from Subv/cb_data

GPU: Handle writes to the CB_DATA method.
This commit is contained in:
bunnei 2018-03-18 19:45:40 -04:00 committed by GitHub
commit 6317a0b2ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 105 additions and 11 deletions

View File

@ -7,6 +7,7 @@ add_library(video_core STATIC
engines/maxwell_3d.h engines/maxwell_3d.h
engines/maxwell_compute.cpp engines/maxwell_compute.cpp
engines/maxwell_compute.h engines/maxwell_compute.h
gpu.cpp
gpu.h gpu.h
memory_manager.cpp memory_manager.cpp
memory_manager.h memory_manager.h

View File

@ -13,6 +13,7 @@ constexpr u32 MacroRegistersStart = 0xE00;
const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers = { const std::unordered_map<u32, Maxwell3D::MethodInfo> Maxwell3D::method_handlers = {
{0xE24, {"SetShader", 5, &Maxwell3D::SetShader}}, {0xE24, {"SetShader", 5, &Maxwell3D::SetShader}},
{0xE2A, {"BindStorageBuffer", 1, &Maxwell3D::BindStorageBuffer}},
}; };
Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} 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."); ASSERT_MSG(regs.code_address.CodeAddress() == 0, "Unexpected CODE_ADDRESS register value.");
break; 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): { case MAXWELL3D_REG_INDEX(cb_bind[0].raw_config): {
ProcessCBBind(Regs::ShaderStage::Vertex); ProcessCBBind(Regs::ShaderStage::Vertex);
break; break;
@ -181,6 +201,26 @@ void Maxwell3D::SetShader(const std::vector<u32>& parameters) {
ProcessCBBind(shader_stage); 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) { void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) {
// Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader 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)]; 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; 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 Engines
} // namespace Tegra } // namespace Tegra

View File

@ -166,7 +166,19 @@ public:
u32 tex_cb_index; 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; std::array<u32, NUM_REGS> reg_array;
}; };
@ -218,6 +230,9 @@ private:
/// Handles a write to the QUERY_GET register. /// Handles a write to the QUERY_GET register.
void ProcessQueryGet(); void ProcessQueryGet();
/// Handles a write to the CB_DATA[i] register.
void ProcessCBData(u32 value);
/// Handles a write to the CB_BIND register. /// Handles a write to the CB_BIND register.
void ProcessCBBind(Regs::ShaderStage stage); void ProcessCBBind(Regs::ShaderStage stage);
@ -226,6 +241,7 @@ private:
/// Method call handlers /// Method call handlers
void SetShader(const std::vector<u32>& parameters); void SetShader(const std::vector<u32>& parameters);
void BindStorageBuffer(const std::vector<u32>& parameters);
struct MethodInfo { struct MethodInfo {
const char* name; const char* name;
@ -249,6 +265,7 @@ ASSERT_REG_POSITION(shader_config[0], 0x800);
ASSERT_REG_POSITION(const_buffer, 0x8E0); ASSERT_REG_POSITION(const_buffer, 0x8E0);
ASSERT_REG_POSITION(cb_bind[0], 0x904); ASSERT_REG_POSITION(cb_bind[0], 0x904);
ASSERT_REG_POSITION(tex_cb_index, 0x982); ASSERT_REG_POSITION(tex_cb_index, 0x982);
ASSERT_REG_POSITION(ssbo_info, 0xD18);
#undef ASSERT_REG_POSITION #undef ASSERT_REG_POSITION

21
src/video_core/gpu.cpp Normal file
View File

@ -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

View File

@ -8,13 +8,16 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "common/common_types.h" #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" #include "video_core/memory_manager.h"
namespace Tegra { namespace Tegra {
namespace Engines {
class Fermi2D;
class Maxwell3D;
class MaxwellCompute;
} // namespace Engines
enum class EngineID { enum class EngineID {
FERMI_TWOD_A = 0x902D, // 2D Engine FERMI_TWOD_A = 0x902D, // 2D Engine
MAXWELL_B = 0xB197, // 3D Engine MAXWELL_B = 0xB197, // 3D Engine
@ -25,13 +28,8 @@ enum class EngineID {
class GPU final { class GPU final {
public: public:
GPU() { GPU();
memory_manager = std::make_unique<MemoryManager>(); ~GPU();
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;
/// Processes a command list stored at the specified address in GPU memory. /// Processes a command list stored at the specified address in GPU memory.
void ProcessCommandList(GPUVAddr address, u32 size); void ProcessCommandList(GPUVAddr address, u32 size);