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);
}
}
}