mirror of
https://github.com/Takiiiiiiii/strato.git
synced 2025-07-17 08:46:39 +00:00
Refactor Comments + Other Minor Fixes
This commit is contained in:
@ -8,9 +8,6 @@
|
||||
#define U32_OFFSET(regs, field) (offsetof(regs, field) / sizeof(u32))
|
||||
|
||||
namespace skyline::gpu {
|
||||
/**
|
||||
* @brief This enumerates the identifiers used to label a specific engine
|
||||
*/
|
||||
enum class EngineID {
|
||||
Fermi2D = 0x902D,
|
||||
KeplerMemory = 0xA140,
|
||||
@ -20,7 +17,7 @@ namespace skyline::gpu {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This holds the parameters of a GPU engine method call
|
||||
* @brief The parameters of a GPU engine method call
|
||||
*/
|
||||
struct MethodParams {
|
||||
u16 method;
|
||||
@ -31,8 +28,8 @@ namespace skyline::gpu {
|
||||
|
||||
namespace engine {
|
||||
/**
|
||||
* @brief The Engine class provides an interface that can be used to communicate with the GPU's internal engines
|
||||
*/
|
||||
* @brief The Engine class provides an interface that can be used to communicate with the GPU's internal engines
|
||||
*/
|
||||
class Engine {
|
||||
protected:
|
||||
const DeviceState &state;
|
||||
@ -43,8 +40,8 @@ namespace skyline::gpu {
|
||||
virtual ~Engine() = default;
|
||||
|
||||
/**
|
||||
* @brief Calls an engine method with the given parameters
|
||||
*/
|
||||
* @brief Calls an engine method with the given parameters
|
||||
*/
|
||||
virtual void CallMethod(MethodParams params) {
|
||||
state.logger->Warn("Called method in unimplemented engine: 0x{:X} args: 0x{:X}", params.method, params.argument);
|
||||
};
|
||||
|
@ -18,9 +18,8 @@ namespace skyline {
|
||||
class GPFIFO : public Engine {
|
||||
private:
|
||||
/**
|
||||
* @brief This holds the GPFIFO engine's registers
|
||||
* @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/classes/host/clb06f.h#L65
|
||||
*/
|
||||
* @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/classes/host/clb06f.h#L65
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
union Registers {
|
||||
std::array<u32, constant::GpfifoRegisterCount> raw;
|
||||
@ -30,22 +29,22 @@ namespace skyline {
|
||||
Release = 2,
|
||||
AcqGeq = 4,
|
||||
AcqAnd = 8,
|
||||
Reduction = 16
|
||||
Reduction = 16,
|
||||
};
|
||||
|
||||
enum class SemaphoreAcquireSwitch : u8 {
|
||||
Disabled = 0,
|
||||
Enabled = 1
|
||||
Enabled = 1,
|
||||
};
|
||||
|
||||
enum class SemaphoreReleaseWfi : u8 {
|
||||
En = 0,
|
||||
Dis = 1
|
||||
Dis = 1,
|
||||
};
|
||||
|
||||
enum class SemaphoreReleaseSize : u8 {
|
||||
SixteenBytes = 0,
|
||||
FourBytes = 1
|
||||
FourBytes = 1,
|
||||
};
|
||||
|
||||
enum class SemaphoreReduction : u8 {
|
||||
@ -56,39 +55,39 @@ namespace skyline {
|
||||
Or = 4,
|
||||
Add = 5,
|
||||
Inc = 6,
|
||||
Dec = 7
|
||||
Dec = 7,
|
||||
};
|
||||
|
||||
enum class SemaphoreFormat : u8 {
|
||||
Signed = 0,
|
||||
Unsigned = 1
|
||||
Unsigned = 1,
|
||||
};
|
||||
|
||||
enum class MemOpTlbInvalidatePdb : u8 {
|
||||
One = 0,
|
||||
All = 1
|
||||
All = 1,
|
||||
};
|
||||
|
||||
enum class SyncpointOperation : u8 {
|
||||
Wait = 0,
|
||||
Incr = 1
|
||||
Incr = 1,
|
||||
};
|
||||
|
||||
enum class SyncpointWaitSwitch : u8 {
|
||||
Dis = 0,
|
||||
En = 1
|
||||
En = 1,
|
||||
};
|
||||
|
||||
enum class WfiScope : u8 {
|
||||
CurrentScgType = 0,
|
||||
All = 1
|
||||
All = 1,
|
||||
};
|
||||
|
||||
enum class YieldOp : u8 {
|
||||
Nop = 0,
|
||||
PbdmaTimeslice = 1,
|
||||
RunlistTimeslice = 2,
|
||||
Tsg = 3
|
||||
Tsg = 3,
|
||||
};
|
||||
|
||||
struct {
|
||||
|
@ -16,16 +16,16 @@ namespace skyline {
|
||||
|
||||
namespace gpu::engine {
|
||||
/**
|
||||
* @brief The Maxwell 3D engine handles processing 3D graphics
|
||||
*/
|
||||
* @brief The Maxwell 3D engine handles processing 3D graphics
|
||||
*/
|
||||
class Maxwell3D : public Engine {
|
||||
private:
|
||||
std::array<size_t, 0x80> macroPositions{}; //!< This holds the positions of each individual macro in macro memory, there can be a maximum of 0x80 macros at any one time
|
||||
std::array<size_t, 0x80> macroPositions{}; //!< The positions of each individual macro in macro memory, there can be a maximum of 0x80 macros at any one time
|
||||
|
||||
struct {
|
||||
u32 index;
|
||||
std::vector<u32> arguments;
|
||||
} macroInvocation{}; //!< This hold the index and arguments of the macro that is pending execution
|
||||
} macroInvocation{}; //!< Data for a macro that is pending execution
|
||||
|
||||
MacroInterpreter macroInterpreter;
|
||||
|
||||
@ -35,9 +35,8 @@ namespace skyline {
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief This holds the Maxwell3D engine's register space
|
||||
* @url https://github.com/devkitPro/deko3d/blob/master/source/maxwell/engine_3d.def#L478
|
||||
*/
|
||||
* @url https://github.com/devkitPro/deko3d/blob/master/source/maxwell/engine_3d.def#L478
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
union Registers {
|
||||
std::array<u32, constant::Maxwell3DRegisterCounter> raw;
|
||||
@ -56,7 +55,7 @@ namespace skyline {
|
||||
MethodTrack = 0,
|
||||
MethodTrackWithFilter = 1,
|
||||
MethodPassthrough = 2,
|
||||
MethodReplay = 3
|
||||
MethodReplay = 3,
|
||||
};
|
||||
|
||||
struct ViewportTransform {
|
||||
@ -196,7 +195,7 @@ namespace skyline {
|
||||
SubtractGL = 0x8007,
|
||||
ReverseSubtractGL = 0x8008,
|
||||
MinimumGL = 0x800A,
|
||||
MaximumGL = 0x800B
|
||||
MaximumGL = 0x800B,
|
||||
};
|
||||
|
||||
enum class Factor : u32 {
|
||||
@ -293,7 +292,7 @@ namespace skyline {
|
||||
Release = 0,
|
||||
Acquire = 1,
|
||||
Counter = 2,
|
||||
Trap = 3
|
||||
Trap = 3,
|
||||
};
|
||||
|
||||
enum class ReductionOp : u8 {
|
||||
@ -348,7 +347,7 @@ namespace skyline {
|
||||
TransformFeedbackOffset = 0x1A,
|
||||
TessControlShaderInvocations = 0x1B,
|
||||
TessEvaluationShaderInvocations = 0x1D,
|
||||
TessEvaluationShaderPrimitives = 0x1F
|
||||
TessEvaluationShaderPrimitives = 0x1F,
|
||||
};
|
||||
|
||||
enum class StructureSize : u8 {
|
||||
@ -375,7 +374,7 @@ namespace skyline {
|
||||
|
||||
enum class CoordOrigin : u8 {
|
||||
LowerLeft = 0,
|
||||
UpperLeft = 1
|
||||
UpperLeft = 1,
|
||||
};
|
||||
|
||||
struct {
|
||||
@ -559,10 +558,10 @@ namespace skyline {
|
||||
static_assert(sizeof(Registers) == (constant::Maxwell3DRegisterCounter * sizeof(u32)));
|
||||
#pragma pack(pop)
|
||||
|
||||
Registers registers{}; //!< The Maxwell 3D register space
|
||||
Registers registers{};
|
||||
Registers shadowRegisters{}; //!< The shadow registers, their function is controlled by the 'shadowRamControl' register
|
||||
|
||||
std::array<u32, 0x10000> macroCode{}; //!< This is used to store GPU macros, the 256kb size is from Ryujinx
|
||||
std::array<u32, 0x10000> macroCode{}; //!< This stores GPU macros, the 256kb size is from Ryujinx
|
||||
|
||||
Maxwell3D(const DeviceState &state);
|
||||
|
||||
|
@ -4,14 +4,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include "engines/engine.h"
|
||||
#include "engines/gpfifo.h"
|
||||
#include "memory_manager.h"
|
||||
|
||||
namespace skyline::gpu {
|
||||
namespace gpfifo {
|
||||
/**
|
||||
* @brief This contains a single GPFIFO entry that is submitted through 'SubmitGpfifo'
|
||||
* @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
|
||||
*/
|
||||
@ -72,7 +71,7 @@ namespace skyline::gpu {
|
||||
static_assert(sizeof(GpEntry) == sizeof(u64));
|
||||
|
||||
/**
|
||||
* @brief This holds a single pushbuffer method header that describes a compressed method sequence
|
||||
* @brief A single pushbuffer method header that describes a compressed method sequence
|
||||
* @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/manuals/volta/gv100/dev_ram.ref.txt#L850
|
||||
* @url https://github.com/NVIDIA/open-gpu-doc/blob/ab27fc22db5de0d02a4cabe08e555663b62db4d4/classes/host/clb06f.h#L179
|
||||
*/
|
||||
@ -84,7 +83,7 @@ namespace skyline::gpu {
|
||||
Grp0SetSubDevMask = 1,
|
||||
Grp0StoreSubDevMask = 2,
|
||||
Grp0UseSubDevMask = 3,
|
||||
Grp2NonIncMethod = 0
|
||||
Grp2NonIncMethod = 0,
|
||||
};
|
||||
|
||||
enum class SecOp : u8 {
|
||||
@ -95,7 +94,7 @@ namespace skyline::gpu {
|
||||
ImmdDataMethod = 4,
|
||||
OneInc = 5,
|
||||
Reserved6 = 6,
|
||||
EndPbSegment = 7
|
||||
EndPbSegment = 7,
|
||||
};
|
||||
|
||||
u16 methodAddress : 12;
|
||||
@ -128,7 +127,7 @@ namespace skyline::gpu {
|
||||
class GPFIFO {
|
||||
private:
|
||||
/**
|
||||
* @brief This is used to hold a pushbuffer's GPFIFO entry and contents, pushbuffers are made up of several 32-bit words
|
||||
* @brief A pushbuffer is a descriptor of tasks that need to be executed for a specific client
|
||||
*/
|
||||
struct PushBuffer {
|
||||
GpEntry gpEntry;
|
||||
@ -149,7 +148,7 @@ namespace skyline::gpu {
|
||||
engine::GPFIFO gpfifoEngine; //!< The engine for processing GPFIFO method calls
|
||||
std::array<std::shared_ptr<engine::Engine>, 8> subchannels;
|
||||
std::queue<PushBuffer> pushBufferQueue;
|
||||
skyline::Mutex pushBufferQueueLock; //!< This is used to lock pushbuffer queue insertions as the GPU runs on a seperate thread
|
||||
skyline::Mutex pushBufferQueueLock; //!< Synchronizes pushbuffer queue insertions as the GPU is multi-threaded
|
||||
|
||||
/**
|
||||
* @brief Processes a pushbuffer segment, calling methods as needed
|
||||
@ -157,7 +156,7 @@ namespace skyline::gpu {
|
||||
void Process(const std::vector<u32> &segment);
|
||||
|
||||
/**
|
||||
* @brief This sends a method call to the GPU hardware
|
||||
* @brief Sends a method call to the GPU hardware
|
||||
*/
|
||||
void Send(MethodParams params);
|
||||
|
||||
|
@ -15,9 +15,6 @@ namespace skyline::gpu {
|
||||
*/
|
||||
class MacroInterpreter {
|
||||
private:
|
||||
/**
|
||||
* @brief This holds a single macro opcode
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
union Opcode {
|
||||
u32 raw;
|
||||
@ -98,11 +95,10 @@ namespace skyline::gpu {
|
||||
static_assert(sizeof(Opcode) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief This holds information about the Maxwell 3D method to be called in 'Send'
|
||||
* @brief Metadata about the Maxwell 3D method to be called in 'Send'
|
||||
*/
|
||||
union MethodAddress {
|
||||
u32 raw;
|
||||
|
||||
struct {
|
||||
u16 address : 12;
|
||||
u8 increment : 6;
|
||||
|
@ -11,23 +11,23 @@ namespace skyline::gpu::vmm {
|
||||
|
||||
// Create the initial chunk that will be split to create new chunks
|
||||
ChunkDescriptor baseChunk(GpuAddressSpaceBase, GpuAddressSpaceSize, 0, ChunkState::Unmapped);
|
||||
chunkList.push_back(baseChunk);
|
||||
chunks.push_back(baseChunk);
|
||||
}
|
||||
|
||||
std::optional<ChunkDescriptor> MemoryManager::FindChunk(u64 size, ChunkState state) {
|
||||
auto chunk{std::find_if(chunkList.begin(), chunkList.end(), [size, state](const ChunkDescriptor &chunk) -> bool {
|
||||
auto chunk{std::find_if(chunks.begin(), chunks.end(), [size, state](const ChunkDescriptor &chunk) -> bool {
|
||||
return chunk.size > size && chunk.state == state;
|
||||
})};
|
||||
|
||||
if (chunk != chunkList.end())
|
||||
if (chunk != chunks.end())
|
||||
return *chunk;
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
u64 MemoryManager::InsertChunk(const ChunkDescriptor &newChunk) {
|
||||
auto chunkEnd{chunkList.end()};
|
||||
for (auto chunk{chunkList.begin()}; chunk != chunkEnd; chunk++) {
|
||||
auto chunkEnd{chunks.end()};
|
||||
for (auto chunk{chunks.begin()}; chunk != chunkEnd; chunk++) {
|
||||
if (chunk->CanContain(newChunk)) {
|
||||
auto oldChunk{*chunk};
|
||||
u64 newSize{newChunk.address - chunk->address};
|
||||
@ -38,11 +38,11 @@ namespace skyline::gpu::vmm {
|
||||
} else {
|
||||
chunk->size = newSize;
|
||||
|
||||
chunk = chunkList.insert(std::next(chunk), newChunk);
|
||||
chunk = chunks.insert(std::next(chunk), newChunk);
|
||||
}
|
||||
|
||||
if (extension)
|
||||
chunkList.insert(std::next(chunk), ChunkDescriptor(newChunk.address + newChunk.size, extension, (oldChunk.state == ChunkState::Mapped) ? (oldChunk.cpuAddress + newSize + newChunk.size) : 0, oldChunk.state));
|
||||
chunks.insert(std::next(chunk), ChunkDescriptor(newChunk.address + newChunk.size, extension, (oldChunk.state == ChunkState::Mapped) ? (oldChunk.cpuAddress + newSize + newChunk.size) : 0, oldChunk.state));
|
||||
|
||||
return newChunk.address;
|
||||
} else if (chunk->address + chunk->size > newChunk.address) {
|
||||
@ -54,8 +54,8 @@ namespace skyline::gpu::vmm {
|
||||
if (tailChunk->address + tailChunk->size >= newChunk.address + newChunk.size)
|
||||
break;
|
||||
|
||||
tailChunk = chunkList.erase(tailChunk);
|
||||
chunkEnd = chunkList.end();
|
||||
tailChunk = chunks.erase(tailChunk);
|
||||
chunkEnd = chunks.end();
|
||||
}
|
||||
|
||||
// The given chunk is too large to fit into existing chunks
|
||||
@ -74,7 +74,7 @@ namespace skyline::gpu::vmm {
|
||||
if (headChunk->size == 0)
|
||||
*headChunk = newChunk;
|
||||
else
|
||||
chunkList.insert(std::next(headChunk), newChunk);
|
||||
chunks.insert(std::next(headChunk), newChunk);
|
||||
|
||||
return newChunk.address;
|
||||
}
|
||||
@ -132,11 +132,11 @@ namespace skyline::gpu::vmm {
|
||||
if (!util::IsAligned(address, constant::GpuPageSize))
|
||||
return false;
|
||||
|
||||
auto chunk{std::find_if(chunkList.begin(), chunkList.end(), [address](const ChunkDescriptor &chunk) -> bool {
|
||||
auto chunk{std::find_if(chunks.begin(), chunks.end(), [address](const ChunkDescriptor &chunk) -> bool {
|
||||
return chunk.address == address;
|
||||
})};
|
||||
|
||||
if (chunk == chunkList.end())
|
||||
if (chunk == chunks.end())
|
||||
return false;
|
||||
|
||||
chunk->state = ChunkState::Reserved;
|
||||
@ -146,11 +146,11 @@ namespace skyline::gpu::vmm {
|
||||
}
|
||||
|
||||
void MemoryManager::Read(u8 *destination, u64 address, u64 size) const {
|
||||
auto chunk{std::upper_bound(chunkList.begin(), chunkList.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool {
|
||||
auto chunk{std::upper_bound(chunks.begin(), chunks.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool {
|
||||
return address < chunk.address;
|
||||
})};
|
||||
|
||||
if (chunk == chunkList.end() || chunk->state != ChunkState::Mapped)
|
||||
if (chunk == chunks.end() || chunk->state != ChunkState::Mapped)
|
||||
throw exception("Failed to read region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size);
|
||||
|
||||
chunk--;
|
||||
@ -166,7 +166,7 @@ namespace skyline::gpu::vmm {
|
||||
|
||||
size -= readSize;
|
||||
if (size) {
|
||||
if (++chunk == chunkList.end() || chunk->state != ChunkState::Mapped)
|
||||
if (++chunk == chunks.end() || chunk->state != ChunkState::Mapped)
|
||||
throw exception("Failed to read region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size);
|
||||
|
||||
readAddress = chunk->cpuAddress;
|
||||
@ -176,11 +176,11 @@ namespace skyline::gpu::vmm {
|
||||
}
|
||||
|
||||
void MemoryManager::Write(u8 *source, u64 address, u64 size) const {
|
||||
auto chunk{std::upper_bound(chunkList.begin(), chunkList.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool {
|
||||
auto chunk{std::upper_bound(chunks.begin(), chunks.end(), address, [](const u64 address, const ChunkDescriptor &chunk) -> bool {
|
||||
return address < chunk.address;
|
||||
})};
|
||||
|
||||
if (chunk == chunkList.end() || chunk->state != ChunkState::Mapped)
|
||||
if (chunk == chunks.end() || chunk->state != ChunkState::Mapped)
|
||||
throw exception("Failed to write region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size);
|
||||
|
||||
chunk--;
|
||||
@ -196,7 +196,7 @@ namespace skyline::gpu::vmm {
|
||||
|
||||
size -= writeSize;
|
||||
if (size) {
|
||||
if (++chunk == chunkList.end() || chunk->state != ChunkState::Mapped)
|
||||
if (++chunk == chunks.end() || chunk->state != ChunkState::Mapped)
|
||||
throw exception("Failed to write region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size);
|
||||
|
||||
writeAddress = chunk->cpuAddress;
|
||||
|
@ -11,44 +11,38 @@ namespace skyline {
|
||||
}
|
||||
|
||||
namespace gpu::vmm {
|
||||
/**
|
||||
* @brief This enumerates the possible states of a memory chunk
|
||||
*/
|
||||
enum ChunkState {
|
||||
Unmapped, //!< The chunk is unmapped
|
||||
Reserved, //!< The chunk is reserved
|
||||
Mapped //!< The chunk is mapped and a CPU side address is present
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This describes a chunk of memory and all of it's individual attributes
|
||||
*/
|
||||
struct ChunkDescriptor {
|
||||
u64 address; //!< The address of the chunk in the GPU address space
|
||||
u64 size; //!< The size of the chunk in bytes
|
||||
u64 cpuAddress; //!< The address of the chunk in the CPU address space (if mapped)
|
||||
ChunkState state; //!< The state of the chunk
|
||||
ChunkState state;
|
||||
|
||||
ChunkDescriptor(u64 address, u64 size, u64 cpuAddress, ChunkState state) : address(address), size(size), cpuAddress(cpuAddress), state(state) {}
|
||||
|
||||
/**
|
||||
* @param chunk The chunk to check
|
||||
* @return If the given chunk can be contained wholly within this chunk
|
||||
*/
|
||||
* @return If the given chunk can be contained wholly within this chunk
|
||||
*/
|
||||
inline bool CanContain(const ChunkDescriptor &chunk) {
|
||||
return (chunk.address >= this->address) && ((this->size + this->address) >= (chunk.size + chunk.address));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The MemoryManager class handles the mapping of the GPU address space
|
||||
*/
|
||||
* @brief The MemoryManager class handles the mapping of the GPU address space
|
||||
*/
|
||||
class MemoryManager {
|
||||
private:
|
||||
const DeviceState &state;
|
||||
std::vector<ChunkDescriptor> chunks;
|
||||
|
||||
/**
|
||||
* @brief This finds a chunk of the specified type in the GPU address space that is larger than the given size
|
||||
* @brief Finds a chunk of the specified type in the GPU address space that is larger than the given size
|
||||
* @param size The minimum size of the chunk to find
|
||||
* @param state The state desired state of the chunk to find
|
||||
* @return The first unmapped chunk in the GPU address space that fits the requested size
|
||||
@ -56,7 +50,7 @@ namespace skyline {
|
||||
std::optional<ChunkDescriptor> FindChunk(u64 size, ChunkState state);
|
||||
|
||||
/**
|
||||
* @brief This inserts a chunk into the chunk list, resizing and splitting as necessary
|
||||
* @brief Inserts a chunk into the chunk list, resizing and splitting as necessary
|
||||
* @param newChunk The chunk to insert
|
||||
* @return The base virtual GPU address of the inserted chunk
|
||||
*/
|
||||
@ -64,17 +58,16 @@ namespace skyline {
|
||||
|
||||
public:
|
||||
MemoryManager(const DeviceState &state);
|
||||
std::vector<ChunkDescriptor> chunkList; //!< This vector holds all the chunk descriptors
|
||||
|
||||
/**
|
||||
* @brief This reserves a region of the GPU address space so it will not be chosen automatically when mapping
|
||||
* @brief Reserves a region of the GPU address space so it will not be chosen automatically when mapping
|
||||
* @param size The size of the region to reserve
|
||||
* @return The virtual GPU base address of the region base
|
||||
*/
|
||||
u64 ReserveSpace(u64 size);
|
||||
|
||||
/**
|
||||
* @brief This reserves a fixed region of the GPU address space so it will not be chosen automatically when mapping
|
||||
* @brief Reserves a fixed region of the GPU address space so it will not be chosen automatically when mapping
|
||||
* @param address The virtual base address of the region to allocate
|
||||
* @param size The size of the region to allocate
|
||||
* @return The virtual address of the region base
|
||||
@ -82,7 +75,7 @@ namespace skyline {
|
||||
u64 ReserveFixed(u64 address, u64 size);
|
||||
|
||||
/**
|
||||
* @brief This maps a physical CPU memory region to an automatically chosen virtual memory region
|
||||
* @brief Maps a physical CPU memory region to an automatically chosen virtual memory region
|
||||
* @param address The physical CPU address of the region to be mapped into the GPU's address space
|
||||
* @param size The size of the region to map
|
||||
* @return The virtual address of the region base
|
||||
@ -90,7 +83,7 @@ namespace skyline {
|
||||
u64 MapAllocate(u64 address, u64 size);
|
||||
|
||||
/**
|
||||
* @brief This maps a physical CPU memory region to a fixed virtual memory region
|
||||
* @brief Maps a physical CPU memory region to a fixed virtual memory region
|
||||
* @param address The target virtual address of the region
|
||||
* @param cpuAddress The physical CPU address of the region to be mapped into the GPU's address space
|
||||
* @param size The size of the region to map
|
||||
@ -99,7 +92,7 @@ namespace skyline {
|
||||
u64 MapFixed(u64 address, u64 cpuAddress, u64 size);
|
||||
|
||||
/**
|
||||
* @brief This unmaps the chunk that starts at 'offset' from the GPU address space
|
||||
* @brief Unmaps the chunk that starts at 'offset' from the GPU address space
|
||||
* @return Whether the operation succeeded
|
||||
*/
|
||||
bool Unmap(u64 address);
|
||||
@ -108,7 +101,6 @@ namespace skyline {
|
||||
|
||||
/**
|
||||
* @brief Reads in a span from a region of the GPU virtual address space
|
||||
* @tparam T The type of span to read into
|
||||
*/
|
||||
template<typename T>
|
||||
void Read(span<T> destination, u64 address) const {
|
||||
@ -138,7 +130,6 @@ namespace skyline {
|
||||
|
||||
/**
|
||||
* @brief Reads in an object from a region of the GPU virtual address space
|
||||
* @tparam T The type of object to return
|
||||
*/
|
||||
template<typename T>
|
||||
void Write(T source, u64 address) const {
|
||||
|
@ -16,15 +16,12 @@ namespace skyline {
|
||||
*/
|
||||
class Syncpoint {
|
||||
private:
|
||||
/**
|
||||
* @brief This holds information about a single waiter on a syncpoint
|
||||
*/
|
||||
struct Waiter {
|
||||
u32 threshold;
|
||||
std::function<void()> callback;
|
||||
u32 threshold; //!< The syncpoint value to wait on to be reached
|
||||
std::function<void()> callback; //!< The callback to do after the wait has ended
|
||||
};
|
||||
|
||||
Mutex waiterLock; //!< Locks insertions and deletions of waiters
|
||||
Mutex waiterLock; //!< Synchronizes insertions and deletions of waiters
|
||||
std::map<u64, Waiter> waiterMap;
|
||||
u64 nextWaiterId{1};
|
||||
|
||||
|
@ -9,6 +9,22 @@
|
||||
namespace skyline::gpu {
|
||||
GuestTexture::GuestTexture(const DeviceState &state, u64 address, texture::Dimensions dimensions, texture::Format format, texture::TileMode tiling, texture::TileConfig layout) : state(state), address(address), dimensions(dimensions), format(format), tileMode(tiling), tileConfig(layout) {}
|
||||
|
||||
std::shared_ptr<Texture> GuestTexture::InitializeTexture(std::optional<texture::Format> format, std::optional<texture::Dimensions> dimensions, texture::Swizzle swizzle) {
|
||||
if (!host.expired())
|
||||
throw exception("Trying to create multiple Texture objects from a single GuestTexture");
|
||||
auto sharedHost{std::make_shared<Texture>(state, shared_from_this(), dimensions ? *dimensions : this->dimensions, format ? *format : this->format, swizzle)};
|
||||
host = sharedHost;
|
||||
return sharedHost;
|
||||
}
|
||||
|
||||
std::shared_ptr<PresentationTexture> GuestTexture::InitializePresentationTexture() {
|
||||
if (!host.expired())
|
||||
throw exception("Trying to create multiple PresentationTexture objects from a single GuestTexture");
|
||||
auto presentation{std::make_shared<PresentationTexture>(state, shared_from_this(), dimensions, format)};
|
||||
host = std::static_pointer_cast<Texture>(presentation);
|
||||
return presentation;
|
||||
}
|
||||
|
||||
Texture::Texture(const DeviceState &state, std::shared_ptr<GuestTexture> guest, texture::Dimensions dimensions, texture::Format format, texture::Swizzle swizzle) : state(state), guest(guest), dimensions(dimensions), format(format), swizzle(swizzle) {
|
||||
SynchronizeHost();
|
||||
}
|
||||
|
@ -12,13 +12,10 @@ namespace skyline {
|
||||
}
|
||||
namespace gpu {
|
||||
namespace texture {
|
||||
/*
|
||||
* @brief This is used to hold the dimensions of a surface
|
||||
*/
|
||||
struct Dimensions {
|
||||
u32 width; //!< The width of the surface
|
||||
u32 height; //!< The height of the surface
|
||||
u32 depth; //!< The depth of the surface
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 depth;
|
||||
|
||||
constexpr Dimensions() : width(0), height(0), depth(0) {}
|
||||
|
||||
@ -26,34 +23,25 @@ namespace skyline {
|
||||
|
||||
constexpr Dimensions(u32 width, u32 height, u32 depth) : width(width), height(height), depth(depth) {}
|
||||
|
||||
/**
|
||||
* @return If the specified dimension is equal to this one
|
||||
*/
|
||||
constexpr inline bool operator==(const Dimensions &dimensions) {
|
||||
constexpr bool operator==(const Dimensions &dimensions) {
|
||||
return (width == dimensions.width) && (height == dimensions.height) && (depth == dimensions.depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the specified dimension is not equal to this one
|
||||
*/
|
||||
constexpr inline bool operator!=(const Dimensions &dimensions) {
|
||||
constexpr bool operator!=(const Dimensions &dimensions) {
|
||||
return (width != dimensions.width) || (height != dimensions.height) || (depth != dimensions.depth);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This is used to hold the attributes of a texture format
|
||||
* @note Blocks refers to the atomic unit of a compressed format (IE: The minimum amount of data that can be decompressed)
|
||||
*/
|
||||
struct Format {
|
||||
u8 bpb; //!< Bytes Per Block, this is to accommodate compressed formats
|
||||
u16 blockHeight; //!< The height of a single block
|
||||
u16 blockWidth; //!< The width of a single block
|
||||
vk::Format vkFormat; //!< The underlying Vulkan type of the format
|
||||
u8 bpb; //!< Bytes Per Block, this is used instead of bytes per pixel as that might not be a whole number for compressed formats
|
||||
u16 blockHeight; //!< The height of a block in pixels
|
||||
u16 blockWidth; //!< The width of a block in pixels
|
||||
vk::Format vkFormat;
|
||||
|
||||
/**
|
||||
* @return If this is a compressed texture format or not
|
||||
*/
|
||||
inline constexpr bool IsCompressed() {
|
||||
constexpr bool IsCompressed() {
|
||||
return (blockHeight != 1) || (blockWidth != 1);
|
||||
}
|
||||
|
||||
@ -63,42 +51,32 @@ namespace skyline {
|
||||
* @param depth The depth of the texture in layers
|
||||
* @return The size of the texture in bytes
|
||||
*/
|
||||
inline constexpr size_t GetSize(u32 width, u32 height, u32 depth = 1) {
|
||||
constexpr size_t GetSize(u32 width, u32 height, u32 depth = 1) {
|
||||
return (((width / blockWidth) * (height / blockHeight)) * bpb) * depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dimensions The dimensions of a texture
|
||||
* @return The size of the texture in bytes
|
||||
*/
|
||||
inline constexpr size_t GetSize(Dimensions dimensions) {
|
||||
constexpr size_t GetSize(Dimensions dimensions) {
|
||||
return GetSize(dimensions.width, dimensions.height, dimensions.depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the specified format is equal to this one
|
||||
*/
|
||||
inline constexpr bool operator==(const Format &format) {
|
||||
constexpr bool operator==(const Format &format) {
|
||||
return vkFormat == format.vkFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the specified format is not equal to this one
|
||||
*/
|
||||
inline constexpr bool operator!=(const Format &format) {
|
||||
constexpr bool operator!=(const Format &format) {
|
||||
return vkFormat != format.vkFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If this format is actually valid or not
|
||||
*/
|
||||
inline constexpr operator bool() {
|
||||
constexpr operator bool() {
|
||||
return bpb;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This describes the linearity of a texture. Refer to Chapter 20.1 of the Tegra X1 TRM for information.
|
||||
* @brief The linearity of a texture, refer to Chapter 20.1 of the Tegra X1 TRM for information
|
||||
*/
|
||||
enum class TileMode {
|
||||
Linear, //!< This is a purely linear texture
|
||||
@ -107,7 +85,7 @@ namespace skyline {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This holds the parameters of the tiling mode, covered in Table 76 in the Tegra X1 TRM
|
||||
* @brief The parameters of the tiling mode, covered in Table 76 in the Tegra X1 TRM
|
||||
*/
|
||||
union TileConfig {
|
||||
struct {
|
||||
@ -118,9 +96,6 @@ namespace skyline {
|
||||
u32 pitch; //!< The pitch of the texture if it's pitch linear
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This enumerates all of the channel swizzle options
|
||||
*/
|
||||
enum class SwizzleChannel {
|
||||
Zero, //!< Write 0 to the channel
|
||||
One, //!< Write 1 to the channel
|
||||
@ -130,9 +105,6 @@ namespace skyline {
|
||||
Alpha, //!< Alpha channel
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This holds all of the texture swizzles on each color channel
|
||||
*/
|
||||
struct Swizzle {
|
||||
SwizzleChannel red{SwizzleChannel::Red}; //!< Swizzle for the red channel
|
||||
SwizzleChannel green{SwizzleChannel::Green}; //!< Swizzle for the green channel
|
||||
@ -145,109 +117,95 @@ namespace skyline {
|
||||
class PresentationTexture;
|
||||
|
||||
/**
|
||||
* @brief This class is used to hold metadata about a guest texture and can be used to create a host Texture object
|
||||
* @brief A texture present in guest memory, it can be used to create a corresponding Texture object for usage on the host
|
||||
*/
|
||||
class GuestTexture : public std::enable_shared_from_this<GuestTexture> {
|
||||
private:
|
||||
const DeviceState &state; //!< The state of the device
|
||||
const DeviceState &state;
|
||||
|
||||
public:
|
||||
u64 address; //!< The address of the texture in guest memory
|
||||
std::shared_ptr<Texture> host; //!< The corresponding host texture object
|
||||
texture::Dimensions dimensions; //!< The dimensions of the texture
|
||||
texture::Format format; //!< The format of the texture
|
||||
texture::TileMode tileMode; //!< The tiling mode of the texture
|
||||
texture::TileConfig tileConfig; //!< The tiling configuration of the texture
|
||||
std::weak_ptr<Texture> host; //!< A host texture (if any) that was created from this guest texture
|
||||
texture::Dimensions dimensions;
|
||||
texture::Format format;
|
||||
texture::TileMode tileMode;
|
||||
texture::TileConfig tileConfig;
|
||||
|
||||
GuestTexture(const DeviceState &state, u64 address, texture::Dimensions dimensions, texture::Format format, texture::TileMode tileMode = texture::TileMode::Linear, texture::TileConfig tileConfig = {});
|
||||
|
||||
inline constexpr size_t Size() {
|
||||
constexpr size_t Size() {
|
||||
return format.GetSize(dimensions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This creates a corresponding host texture object for this guest texture
|
||||
* @brief Creates a corresponding host texture object for this guest texture
|
||||
* @param format The format of the host texture (Defaults to the format of the guest texture)
|
||||
* @param dimensions The dimensions of the host texture (Defaults to the dimensions of the host texture)
|
||||
* @param swizzle The channel swizzle of the host texture (Defaults to no channel swizzling)
|
||||
* @return A shared pointer to the host texture object
|
||||
* @note There can only be one host texture for a corresponding guest texture
|
||||
*/
|
||||
std::shared_ptr<Texture> InitializeTexture(std::optional<texture::Format> format = std::nullopt, std::optional<texture::Dimensions> dimensions = std::nullopt, texture::Swizzle swizzle = {}) {
|
||||
if (host)
|
||||
throw exception("Trying to create multiple Texture objects from a single GuestTexture");
|
||||
host = std::make_shared<Texture>(state, shared_from_this(), dimensions ? *dimensions : this->dimensions, format ? *format : this->format, swizzle);
|
||||
return host;
|
||||
}
|
||||
std::shared_ptr<Texture> InitializeTexture(std::optional<texture::Format> format = std::nullopt, std::optional<texture::Dimensions> dimensions = std::nullopt, texture::Swizzle swizzle = {});
|
||||
|
||||
protected:
|
||||
std::shared_ptr<PresentationTexture> InitializePresentationTexture() {
|
||||
if (host)
|
||||
throw exception("Trying to create multiple PresentationTexture objects from a single GuestTexture");
|
||||
auto presentation{std::make_shared<PresentationTexture>(state, shared_from_this(), dimensions, format)};
|
||||
host = std::static_pointer_cast<Texture>(presentation);
|
||||
return presentation;
|
||||
}
|
||||
std::shared_ptr<PresentationTexture> InitializePresentationTexture();
|
||||
|
||||
friend service::hosbinder::GraphicBufferProducer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This class is used to store a texture which is backed by host objects
|
||||
* @brief A texture which is backed by host constructs while being synchronized with the underlying guest texture
|
||||
*/
|
||||
class Texture {
|
||||
private:
|
||||
const DeviceState &state; //!< The state of the device
|
||||
const DeviceState &state;
|
||||
|
||||
public:
|
||||
std::vector<u8> backing; //!< The object that holds a host copy of the guest texture (Will be replaced with a vk::Image)
|
||||
std::shared_ptr<GuestTexture> guest; //!< The corresponding guest texture object
|
||||
texture::Dimensions dimensions; //!< The dimensions of the texture
|
||||
texture::Format format; //!< The format of the host texture
|
||||
texture::Swizzle swizzle; //!< The swizzle of the host texture
|
||||
std::shared_ptr<GuestTexture> guest; //!< The guest texture from which this was created, it is required for syncing
|
||||
texture::Dimensions dimensions;
|
||||
texture::Format format;
|
||||
texture::Swizzle swizzle;
|
||||
|
||||
public:
|
||||
Texture(const DeviceState &state, std::shared_ptr<GuestTexture> guest, texture::Dimensions dimensions, texture::Format format, texture::Swizzle swizzle);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief This convert this texture to the specified tiling mode
|
||||
* @brief Convert this texture to the specified tiling mode
|
||||
* @param tileMode The tiling mode to convert it to
|
||||
* @param tileConfig The configuration for the tiling mode (Can be default argument for Linear)
|
||||
*/
|
||||
void ConvertTileMode(texture::TileMode tileMode, texture::TileConfig tileConfig = {});
|
||||
|
||||
/**
|
||||
* @brief This sets the texture dimensions to the specified ones (As long as they are within the GuestTexture's range)
|
||||
* @param dimensions The dimensions to adjust the texture to
|
||||
* @brief Converts the texture dimensions to the specified ones (As long as they are within the GuestTexture's range)
|
||||
*/
|
||||
void SetDimensions(texture::Dimensions dimensions);
|
||||
|
||||
/**
|
||||
* @brief This sets the format to the specified one
|
||||
* @param format The format to change the texture to
|
||||
* @brief Converts the texture to have the specified format
|
||||
*/
|
||||
void SetFormat(texture::Format format);
|
||||
|
||||
/**
|
||||
* @brief This sets the channel swizzle to the specified one
|
||||
* @param swizzle The channel swizzle to the change the texture to
|
||||
* @brief Change the texture channel swizzle to the specified one
|
||||
*/
|
||||
void SetSwizzle(texture::Swizzle swizzle);
|
||||
|
||||
/**
|
||||
* @brief This synchronizes the host texture with the guest after it has been modified
|
||||
* @brief Synchronizes the host texture with the guest after it has been modified
|
||||
*/
|
||||
void SynchronizeHost();
|
||||
|
||||
/**
|
||||
* @brief This synchronizes the guest texture with the host texture after it has been modified
|
||||
* @brief Synchronizes the guest texture with the host texture after it has been modified
|
||||
*/
|
||||
void SynchronizeGuest();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This class is used to hold a texture object alongside a release callback used for display presentation
|
||||
* @brief A texture object alongside a release callback used for display presentation
|
||||
*/
|
||||
class PresentationTexture : public Texture {
|
||||
public:
|
||||
|
Reference in New Issue
Block a user