From ac61a7d1e6575bde260ba482ba3594e70fcac358 Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 12 Feb 2018 12:34:41 -0500 Subject: [PATCH] GPU: Partially implemented the QUERY_* registers in the Maxwell3D engine. Only QueryMode::Write is supported at the moment. --- src/video_core/engines/maxwell_3d.cpp | 40 ++++++++++++++++++- src/video_core/engines/maxwell_3d.h | 56 ++++++++++++++++++++++++++- src/video_core/gpu.h | 2 +- 3 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index ccdb310f0d..9f699399fc 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -2,12 +2,50 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/assert.h" #include "video_core/engines/maxwell_3d.h" namespace Tegra { namespace Engines { -void Maxwell3D::WriteReg(u32 method, u32 value) {} +Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} +void Maxwell3D::WriteReg(u32 method, u32 value) { + ASSERT_MSG(method < Regs::NUM_REGS, + "Invalid Maxwell3D register, increase the size of the Regs structure"); + + regs.reg_array[method] = value; + +#define MAXWELL3D_REG_INDEX(field_name) (offsetof(Regs, field_name) / sizeof(u32)) + + switch (method) { + case MAXWELL3D_REG_INDEX(query.query_get): { + ProcessQueryGet(); + break; + } + default: + break; + } + +#undef MAXWELL3D_REG_INDEX +} + +void Maxwell3D::ProcessQueryGet() { + GPUVAddr sequence_address = regs.query.QueryAddress(); + // Since the sequence address is given as a GPU VAddr, we have to convert it to an application + // VAddr before writing. + VAddr address = memory_manager.PhysicalToVirtualAddress(sequence_address); + + switch (regs.query.query_get.mode) { + case Regs::QueryMode::Write: { + // Write the current query sequence to the sequence address. + u32 sequence = regs.query.query_sequence; + Memory::Write32(address, sequence); + break; + } + default: + UNIMPLEMENTED_MSG("Query mode %u not implemented", regs.query.query_get.mode.Value()); + } +} } // namespace Engines } // namespace Tegra diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 0f4ae1328a..5cd2ecd209 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -4,19 +4,73 @@ #pragma once +#include "common/bit_field.h" +#include "common/common_funcs.h" #include "common/common_types.h" +#include "video_core/memory_manager.h" namespace Tegra { namespace Engines { class Maxwell3D final { public: - Maxwell3D() = default; + Maxwell3D(MemoryManager& memory_manager); ~Maxwell3D() = default; /// Write the value to the register identified by method. void WriteReg(u32 method, u32 value); + + /// Register structure of the Maxwell3D engine. + /// TODO(Subv): This structure will need to be made bigger as more registers are discovered. + struct Regs { + static constexpr size_t NUM_REGS = 0xE36; + + enum class QueryMode : u32 { + Write = 0, + Sync = 1, + }; + + union { + struct { + INSERT_PADDING_WORDS(0x6C0); + struct { + u32 query_address_high; + u32 query_address_low; + u32 query_sequence; + union { + u32 raw; + BitField<0, 2, QueryMode> mode; + BitField<4, 1, u32> fence; + BitField<12, 4, u32> unit; + } query_get; + + GPUVAddr QueryAddress() const { + return static_cast( + (static_cast(query_address_high) << 32) | query_address_low); + } + } query; + INSERT_PADDING_WORDS(0x772); + }; + std::array reg_array; + }; + } regs{}; + + static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size"); + +private: + /// Handles a write to the QUERY_GET register. + void ProcessQueryGet(); + + MemoryManager& memory_manager; }; +#define ASSERT_REG_POSITION(field_name, position) \ + static_assert(offsetof(Maxwell3D::Regs, field_name) == position * 4, \ + "Field " #field_name " has invalid position") + +ASSERT_REG_POSITION(query, 0x6C0); + +#undef ASSERT_REG_POSITION + } // namespace Engines } // namespace Tegra diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index a961f3fd4e..ba7781756c 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -26,7 +26,7 @@ class GPU final { public: GPU() { memory_manager = std::make_unique(); - maxwell_3d = std::make_unique(); + maxwell_3d = std::make_unique(*memory_manager); fermi_2d = std::make_unique(); maxwell_compute = std::make_unique(); }