diff options
| -rw-r--r-- | src/video_core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/video_core/command_processor.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/engines/kepler_memory.cpp | 45 | ||||
| -rw-r--r-- | src/video_core/engines/kepler_memory.h | 90 | ||||
| -rw-r--r-- | src/video_core/gpu.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/gpu.h | 3 | 
6 files changed, 146 insertions, 0 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 65b5f57c3..4a79ce39c 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -5,6 +5,8 @@ add_library(video_core STATIC      debug_utils/debug_utils.h      engines/fermi_2d.cpp      engines/fermi_2d.h +    engines/kepler_memory.cpp +    engines/kepler_memory.h      engines/maxwell_3d.cpp      engines/maxwell_3d.h      engines/maxwell_compute.cpp diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index 2625ddfdc..f1aa6091b 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -14,6 +14,7 @@  #include "core/tracer/recorder.h"  #include "video_core/command_processor.h"  #include "video_core/engines/fermi_2d.h" +#include "video_core/engines/kepler_memory.h"  #include "video_core/engines/maxwell_3d.h"  #include "video_core/engines/maxwell_compute.h"  #include "video_core/engines/maxwell_dma.h" @@ -69,6 +70,9 @@ void GPU::ProcessCommandLists(const std::vector<CommandListHeader>& commands) {          case EngineID::MAXWELL_DMA_COPY_A:              maxwell_dma->WriteReg(method, value);              break; +        case EngineID::KEPLER_INLINE_TO_MEMORY_B: +            kepler_memory->WriteReg(method, value); +            break;          default:              UNIMPLEMENTED_MSG("Unimplemented engine");          } diff --git a/src/video_core/engines/kepler_memory.cpp b/src/video_core/engines/kepler_memory.cpp new file mode 100644 index 000000000..66ae6332d --- /dev/null +++ b/src/video_core/engines/kepler_memory.cpp @@ -0,0 +1,45 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#include "core/memory.h" +#include "video_core/engines/kepler_memory.h" + +namespace Tegra::Engines { + +KeplerMemory::KeplerMemory(MemoryManager& memory_manager) : memory_manager(memory_manager) {} +KeplerMemory::~KeplerMemory() = default; + +void KeplerMemory::WriteReg(u32 method, u32 value) { +    ASSERT_MSG(method < Regs::NUM_REGS, +               "Invalid KeplerMemory register, increase the size of the Regs structure"); + +    regs.reg_array[method] = value; + +    switch (method) { +    case KEPLERMEMORY_REG_INDEX(exec): { +        state.write_offset = 0; +        break; +    } +    case KEPLERMEMORY_REG_INDEX(data): { +        ProcessData(value); +        break; +    } +    } +} + +void KeplerMemory::ProcessData(u32 data) { +    ASSERT_MSG(regs.exec.linear, "Non-linear uploads are not supported"); +    ASSERT(regs.dest.x == 0 && regs.dest.y == 0 && regs.dest.z == 0); + +    GPUVAddr address = regs.dest.Address(); +    VAddr dest_address = +        *memory_manager.GpuToCpuAddress(address + state.write_offset * sizeof(u32)); + +    Memory::Write32(dest_address, data); + +    state.write_offset++; +} + +} // namespace Tegra::Engines diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h new file mode 100644 index 000000000..b0d0078cf --- /dev/null +++ b/src/video_core/engines/kepler_memory.h @@ -0,0 +1,90 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <array> +#include "common/assert.h" +#include "common/bit_field.h" +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "video_core/memory_manager.h" + +namespace Tegra::Engines { + +#define KEPLERMEMORY_REG_INDEX(field_name)                                                         \ +    (offsetof(Tegra::Engines::KeplerMemory::Regs, field_name) / sizeof(u32)) + +class KeplerMemory final { +public: +    KeplerMemory(MemoryManager& memory_manager); +    ~KeplerMemory(); + +    /// Write the value to the register identified by method. +    void WriteReg(u32 method, u32 value); + +    struct Regs { +        static constexpr size_t NUM_REGS = 0x7F; + +        union { +            struct { +                INSERT_PADDING_WORDS(0x60); + +                u32 line_length_in; +                u32 line_count; + +                struct { +                    u32 address_high; +                    u32 address_low; +                    u32 pitch; +                    u32 block_dimensions; +                    u32 width; +                    u32 height; +                    u32 depth; +                    u32 z; +                    u32 x; +                    u32 y; + +                    GPUVAddr Address() const { +                        return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | +                                                     address_low); +                    } +                } dest; + +                struct { +                    union { +                        BitField<0, 1, u32> linear; +                    }; +                } exec; + +                u32 data; + +                INSERT_PADDING_WORDS(0x11); +            }; +            std::array<u32, NUM_REGS> reg_array; +        }; +    } regs{}; + +    struct { +        u32 write_offset = 0; +    } state{}; + +private: +    MemoryManager& memory_manager; + +    void ProcessData(u32 data); +}; + +#define ASSERT_REG_POSITION(field_name, position)                                                  \ +    static_assert(offsetof(KeplerMemory::Regs, field_name) == position * 4,                        \ +                  "Field " #field_name " has invalid position") + +ASSERT_REG_POSITION(line_length_in, 0x60); +ASSERT_REG_POSITION(line_count, 0x61); +ASSERT_REG_POSITION(dest, 0x62); +ASSERT_REG_POSITION(exec, 0x6C); +ASSERT_REG_POSITION(data, 0x6D); +#undef ASSERT_REG_POSITION + +} // namespace Tegra::Engines diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 86a809f86..baa8b63b7 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -4,6 +4,7 @@  #include "common/assert.h"  #include "video_core/engines/fermi_2d.h" +#include "video_core/engines/kepler_memory.h"  #include "video_core/engines/maxwell_3d.h"  #include "video_core/engines/maxwell_compute.h"  #include "video_core/engines/maxwell_dma.h" @@ -27,6 +28,7 @@ GPU::GPU(VideoCore::RasterizerInterface& rasterizer) {      fermi_2d = std::make_unique<Engines::Fermi2D>(*memory_manager);      maxwell_compute = std::make_unique<Engines::MaxwellCompute>();      maxwell_dma = std::make_unique<Engines::MaxwellDMA>(*memory_manager); +    kepler_memory = std::make_unique<Engines::KeplerMemory>(*memory_manager);  }  GPU::~GPU() = default; diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 589a59b4f..7329ca766 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -102,6 +102,7 @@ class Fermi2D;  class Maxwell3D;  class MaxwellCompute;  class MaxwellDMA; +class KeplerMemory;  } // namespace Engines  enum class EngineID { @@ -146,6 +147,8 @@ private:      std::unique_ptr<Engines::MaxwellCompute> maxwell_compute;      /// DMA engine      std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; +    /// Inline memory engine +    std::unique_ptr<Engines::KeplerMemory> kepler_memory;  };  } // namespace Tegra  | 
