2021-03-24 21:09:21 +01:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <common/circular_queue.h>
|
2023-03-05 22:50:00 +01:00
|
|
|
#include <soc/gm20b/macro/macro_state.h>
|
2021-03-24 21:09:21 +01:00
|
|
|
#include "engines/gpfifo.h"
|
|
|
|
|
|
|
|
namespace skyline::soc::gm20b {
|
2021-10-08 21:25:21 +02:00
|
|
|
struct ChannelContext;
|
|
|
|
|
2022-01-19 21:45:51 +01:00
|
|
|
/**
|
|
|
|
* @brief Mapping of subchannel names to their corresponding subchannel IDs
|
|
|
|
*/
|
|
|
|
enum class SubchannelId : u8 {
|
|
|
|
ThreeD = 0,
|
|
|
|
Compute = 1,
|
|
|
|
Inline2Mem = 2,
|
|
|
|
TwoD = 3,
|
|
|
|
Copy = 4,
|
|
|
|
Software0 = 5,
|
|
|
|
Software1 = 6,
|
|
|
|
Software2 = 7,
|
|
|
|
};
|
|
|
|
|
2021-03-24 21:09:21 +01:00
|
|
|
/**
|
|
|
|
* @brief A GPFIFO entry as submitted through 'SubmitGpfifo'
|
|
|
|
* @url https://nvidia.github.io/open-gpu-doc/manuals/volta/gv100/dev_pbdma.ref.txt
|
|
|
|
* @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/classes/host/clb06f.h#L155
|
|
|
|
*/
|
|
|
|
struct GpEntry {
|
|
|
|
enum class Fetch : u8 {
|
|
|
|
Unconditional = 0,
|
|
|
|
Conditional = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
union {
|
2021-10-11 21:08:42 +02:00
|
|
|
u32 entry0{};
|
2021-03-24 21:09:21 +01:00
|
|
|
|
|
|
|
struct {
|
|
|
|
Fetch fetch : 1;
|
|
|
|
u8 _pad_ : 1;
|
|
|
|
u32 get : 30;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class Opcode : u8 {
|
|
|
|
Nop = 0,
|
|
|
|
Illegal = 1,
|
|
|
|
Crc = 2,
|
|
|
|
PbCrc = 3,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class Priv : u8 {
|
|
|
|
User = 0,
|
|
|
|
Kernel = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class Level : u8 {
|
|
|
|
Main = 0,
|
|
|
|
Subroutine = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class Sync : u8 {
|
|
|
|
Proceed = 0,
|
|
|
|
Wait = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
union {
|
2021-10-11 21:08:42 +02:00
|
|
|
u32 entry1{};
|
2021-03-24 21:09:21 +01:00
|
|
|
|
|
|
|
struct {
|
|
|
|
union {
|
|
|
|
u8 getHi;
|
|
|
|
Opcode opcode;
|
|
|
|
};
|
|
|
|
|
|
|
|
Priv priv : 1;
|
|
|
|
Level level : 1;
|
|
|
|
u32 size : 21;
|
|
|
|
Sync sync : 1;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2021-10-11 21:08:42 +02:00
|
|
|
constexpr GpEntry(u64 gpuAddress, u32 pSize) {
|
|
|
|
getHi = static_cast<u8>(gpuAddress >> 32);
|
|
|
|
get = static_cast<u32>(gpuAddress >> 2);
|
|
|
|
size = pSize;
|
|
|
|
}
|
|
|
|
|
2021-03-24 21:09:21 +01:00
|
|
|
constexpr u64 Address() const {
|
|
|
|
return (static_cast<u64>(getHi) << 32) | (static_cast<u64>(get) << 2);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
static_assert(sizeof(GpEntry) == sizeof(u64));
|
|
|
|
|
|
|
|
/**
|
2021-10-08 21:25:21 +02:00
|
|
|
* @brief The ChannelGpfifo class handles creating pushbuffers from GP entries and then processing them for a single channel
|
2021-10-30 19:55:06 +02:00
|
|
|
* @note A single ChannelGpfifo thread exists per channel, allowing them to run asynchronously
|
|
|
|
* @note This class doesn't perfectly map to any particular hardware component on the X1, it does a mix of the GPU Host PBDMA and handling the GPFIFO entries
|
2021-03-24 21:09:21 +01:00
|
|
|
* @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/manuals/volta/gv100/dev_pbdma.ref.txt#L62
|
|
|
|
*/
|
2021-10-08 21:25:21 +02:00
|
|
|
class ChannelGpfifo {
|
2021-10-13 22:46:30 +02:00
|
|
|
private:
|
2021-03-24 21:09:21 +01:00
|
|
|
const DeviceState &state;
|
2021-10-08 21:25:21 +02:00
|
|
|
ChannelContext &channelCtx;
|
2021-03-24 21:09:21 +01:00
|
|
|
engine::GPFIFO gpfifoEngine; //!< The engine for processing GPFIFO method calls
|
2021-10-08 21:25:21 +02:00
|
|
|
CircularQueue<GpEntry> gpEntries;
|
2021-03-24 21:09:21 +01:00
|
|
|
std::vector<u32> pushBufferData; //!< Persistent vector storing pushbuffer data to avoid constant reallocations
|
2023-03-05 22:50:00 +01:00
|
|
|
bool skipDirtyFlushes{}; //!< If GPU flushing should be skipped when fetching pushbuffer contents
|
2021-03-24 21:09:21 +01:00
|
|
|
|
2021-10-13 22:46:30 +02:00
|
|
|
/**
|
|
|
|
* @brief Holds the required state in order to resume a method started from one call to `Process` in another
|
|
|
|
* @note This is needed as games (especially OpenGL ones) can split method entries over multiple GpEntries
|
|
|
|
*/
|
|
|
|
struct MethodResumeState {
|
|
|
|
u32 remaining; //!< The number of entries left to handle until the method is finished
|
|
|
|
u32 address; //!< The method address in the GPU block specified by `subchannel` that is the target of the command
|
2022-01-19 21:45:51 +01:00
|
|
|
SubchannelId subChannel;
|
2021-10-13 22:46:30 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief This is a simplified version of the full method type enum
|
|
|
|
*/
|
|
|
|
enum class State : u8 {
|
|
|
|
NonInc,
|
|
|
|
Inc,
|
|
|
|
OneInc //!< Will be switched to NonInc after the first call
|
|
|
|
} state; //!< The type of method to resume
|
|
|
|
} resumeState{};
|
|
|
|
|
2022-01-19 21:45:51 +01:00
|
|
|
std::thread thread; //!< The thread that manages processing of pushbuffers
|
2021-10-13 22:46:30 +02:00
|
|
|
|
2021-03-24 21:09:21 +01:00
|
|
|
/**
|
2022-02-22 21:37:31 +01:00
|
|
|
* @brief Sends a method call to the appropriate subchannel and handles macro and GPFIFO methods
|
2021-03-24 21:09:21 +01:00
|
|
|
*/
|
2023-03-05 22:50:00 +01:00
|
|
|
void SendFull(u32 method, GpfifoArgument argument, SubchannelId subchannel, bool lastCall);
|
2022-02-22 21:37:31 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Sends a method call to the appropriate subchannel, macro and GPFIFO methods are not handled
|
|
|
|
*/
|
|
|
|
void SendPure(u32 method, u32 argument, SubchannelId subchannel);
|
2021-10-13 22:46:30 +02:00
|
|
|
|
2022-03-04 20:41:22 +01:00
|
|
|
/**
|
|
|
|
* @brief Sends a batch of method calls all directed at the same method to the appropriate subchannel, macro and GPFIFO methods are not handled
|
|
|
|
*/
|
|
|
|
void SendPureBatchNonInc(u32 method, span<u32> arguments, SubchannelId subChannel);
|
|
|
|
|
2021-03-24 21:09:21 +01:00
|
|
|
/**
|
|
|
|
* @brief Processes the pushbuffer contained within the given GpEntry, calling methods as needed
|
|
|
|
*/
|
|
|
|
void Process(GpEntry gpEntry);
|
|
|
|
|
2021-10-30 19:55:06 +02:00
|
|
|
/**
|
|
|
|
* @brief Executes all pending entries in the FIFO and polls for more
|
|
|
|
*/
|
|
|
|
void Run();
|
|
|
|
|
2021-03-24 21:09:21 +01:00
|
|
|
public:
|
|
|
|
/**
|
2021-10-08 21:25:21 +02:00
|
|
|
* @param numEntries The number of gpEntries to allocate space for in the FIFO
|
2021-03-24 21:09:21 +01:00
|
|
|
*/
|
2021-10-08 21:25:21 +02:00
|
|
|
ChannelGpfifo(const DeviceState &state, ChannelContext &channelCtx, size_t numEntries);
|
|
|
|
|
|
|
|
~ChannelGpfifo();
|
2021-03-24 21:09:21 +01:00
|
|
|
|
|
|
|
/**
|
2021-10-13 22:46:30 +02:00
|
|
|
* @brief Pushes a list of entries to the FIFO, these commands will be executed on calls to 'Process'
|
2021-03-24 21:09:21 +01:00
|
|
|
*/
|
|
|
|
void Push(span<GpEntry> entries);
|
2021-10-11 21:08:42 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Pushes a single entry to the FIFO, these commands will be executed on calls to 'Process'
|
|
|
|
*/
|
|
|
|
void Push(GpEntry entries);
|
2021-03-24 21:09:21 +01:00
|
|
|
};
|
|
|
|
}
|