using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.State; using Ryujinx.Graphics.Shader; namespace Ryujinx.Graphics.Gpu.Shader { /// /// Represents a GPU state and memory accessor. /// class GpuAccessor : TextureDescriptorCapableGpuAccessor, IGpuAccessor { private readonly GpuContext _context; private readonly GpuState _state; private readonly int _stageIndex; private readonly bool _compute; private readonly int _localSizeX; private readonly int _localSizeY; private readonly int _localSizeZ; private readonly int _localMemorySize; private readonly int _sharedMemorySize; /// /// Creates a new instance of the GPU state accessor for graphics shader translation. /// /// GPU context /// Current GPU state /// Graphics shader stage index (0 = Vertex, 4 = Fragment) public GpuAccessor(GpuContext context, GpuState state, int stageIndex) { _context = context; _state = state; _stageIndex = stageIndex; } /// /// Creates a new instance of the GPU state accessor for compute shader translation. /// /// GPU context /// Current GPU state /// Local group size X of the compute shader /// Local group size Y of the compute shader /// Local group size Z of the compute shader /// Local memory size of the compute shader /// Shared memory size of the compute shader public GpuAccessor( GpuContext context, GpuState state, int localSizeX, int localSizeY, int localSizeZ, int localMemorySize, int sharedMemorySize) { _context = context; _state = state; _compute = true; _localSizeX = localSizeX; _localSizeY = localSizeY; _localSizeZ = localSizeZ; _localMemorySize = localMemorySize; _sharedMemorySize = sharedMemorySize; } /// /// Prints a log message. /// /// Message to print public void Log(string message) { Logger.Warning?.Print(LogClass.Gpu, $"Shader translator: {message}"); } /// /// Reads data from GPU memory. /// /// Type of the data to be read /// GPU virtual address of the data /// Data at the memory location public override T MemoryRead(ulong address) { return _state.Channel.MemoryManager.Read(address); } /// /// Checks if a given memory address is mapped. /// /// GPU virtual address to be checked /// True if the address is mapped, false otherwise public bool MemoryMapped(ulong address) { return _state.Channel.MemoryManager.IsMapped(address); } /// /// Queries Local Size X for compute shaders. /// /// Local Size X public int QueryComputeLocalSizeX() => _localSizeX; /// /// Queries Local Size Y for compute shaders. /// /// Local Size Y public int QueryComputeLocalSizeY() => _localSizeY; /// /// Queries Local Size Z for compute shaders. /// /// Local Size Z public int QueryComputeLocalSizeZ() => _localSizeZ; /// /// Queries Local Memory size in bytes for compute shaders. /// /// Local Memory size in bytes public int QueryComputeLocalMemorySize() => _localMemorySize; /// /// Queries Shared Memory size in bytes for compute shaders. /// /// Shared Memory size in bytes public int QueryComputeSharedMemorySize() => _sharedMemorySize; /// /// Queries Constant Buffer usage information. /// /// A mask where each bit set indicates a bound constant buffer public uint QueryConstantBufferUse() { return _compute ? _state.Channel.BufferManager.GetComputeUniformBufferUseMask() : _state.Channel.BufferManager.GetGraphicsUniformBufferUseMask(_stageIndex); } /// /// Queries current primitive topology for geometry shaders. /// /// Current primitive topology public InputTopology QueryPrimitiveTopology() { switch (_context.Methods.Topology) { case PrimitiveTopology.Points: return InputTopology.Points; case PrimitiveTopology.Lines: case PrimitiveTopology.LineLoop: case PrimitiveTopology.LineStrip: return InputTopology.Lines; case PrimitiveTopology.LinesAdjacency: case PrimitiveTopology.LineStripAdjacency: return InputTopology.LinesAdjacency; case PrimitiveTopology.Triangles: case PrimitiveTopology.TriangleStrip: case PrimitiveTopology.TriangleFan: return InputTopology.Triangles; case PrimitiveTopology.TrianglesAdjacency: case PrimitiveTopology.TriangleStripAdjacency: return InputTopology.TrianglesAdjacency; } return InputTopology.Points; } /// /// Queries host storage buffer alignment required. /// /// Host storage buffer alignment in bytes public int QueryStorageBufferOffsetAlignment() => _context.Capabilities.StorageBufferOffsetAlignment; /// /// Queries host support for readable images without a explicit format declaration on the shader. /// /// True if formatted image load is supported, false otherwise public bool QuerySupportsImageLoadFormatted() => _context.Capabilities.SupportsImageLoadFormatted; /// /// Queries host GPU non-constant texture offset support. /// /// True if the GPU and driver supports non-constant texture offsets, false otherwise public bool QuerySupportsNonConstantTextureOffset() => _context.Capabilities.SupportsNonConstantTextureOffset; /// /// Queries host GPU texture shadow LOD support. /// /// True if the GPU and driver supports texture shadow LOD, false otherwise public bool QuerySupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod; /// /// Gets the texture descriptor for a given texture on the pool. /// /// Index of the texture (this is the word offset of the handle in the constant buffer) /// Constant buffer slot for the texture handle /// Texture descriptor public override Image.ITextureDescriptor GetTextureDescriptor(int handle, int cbufSlot) { if (_compute) { return _state.Channel.TextureManager.GetComputeTextureDescriptor(_state, handle, cbufSlot); } else { return _state.Channel.TextureManager.GetGraphicsTextureDescriptor(_state, _stageIndex, handle, cbufSlot); } } /// /// Queries if host state forces early depth testing. /// /// True if early depth testing is forced public bool QueryEarlyZForce() { return _state.Get(MethodOffset.EarlyZForce); } } }