forked from Mirror/Ryujinx
Implement SULD shader instruction (#1117)
* Implement SULD shader instruction * Some nits
This commit is contained in:
parent
4738113f29
commit
03711dd7b5
15 changed files with 620 additions and 109 deletions
|
@ -29,7 +29,26 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
int sharedMemorySize = Math.Min(qmd.SharedMemorySize, _context.Capabilities.MaximumComputeSharedMemorySize);
|
int sharedMemorySize = Math.Min(qmd.SharedMemorySize, _context.Capabilities.MaximumComputeSharedMemorySize);
|
||||||
|
|
||||||
|
uint sbEnableMask = 0;
|
||||||
|
uint ubEnableMask = 0;
|
||||||
|
|
||||||
|
for (int index = 0; index < Constants.TotalCpUniformBuffers; index++)
|
||||||
|
{
|
||||||
|
if (!qmd.ConstantBufferValid(index))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubEnableMask |= 1u << index;
|
||||||
|
|
||||||
|
ulong gpuVa = (uint)qmd.ConstantBufferAddrLower(index) | (ulong)qmd.ConstantBufferAddrUpper(index) << 32;
|
||||||
|
ulong size = (ulong)qmd.ConstantBufferSize(index);
|
||||||
|
|
||||||
|
BufferManager.SetComputeUniformBuffer(index, gpuVa, size);
|
||||||
|
}
|
||||||
|
|
||||||
ComputeShader cs = ShaderCache.GetComputeShader(
|
ComputeShader cs = ShaderCache.GetComputeShader(
|
||||||
|
state,
|
||||||
shaderGpuVa,
|
shaderGpuVa,
|
||||||
qmd.CtaThreadDimension0,
|
qmd.CtaThreadDimension0,
|
||||||
qmd.CtaThreadDimension1,
|
qmd.CtaThreadDimension1,
|
||||||
|
@ -49,25 +68,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
TextureManager.SetComputeTextureBufferIndex(state.Get<int>(MethodOffset.TextureBufferIndex));
|
TextureManager.SetComputeTextureBufferIndex(state.Get<int>(MethodOffset.TextureBufferIndex));
|
||||||
|
|
||||||
ShaderProgramInfo info = cs.Shader.Program.Info;
|
ShaderProgramInfo info = cs.Shader.Program.Info;
|
||||||
|
|
||||||
uint sbEnableMask = 0;
|
|
||||||
uint ubEnableMask = 0;
|
|
||||||
|
|
||||||
for (int index = 0; index < Constants.TotalCpUniformBuffers; index++)
|
|
||||||
{
|
|
||||||
if (!qmd.ConstantBufferValid(index))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ubEnableMask |= 1u << index;
|
|
||||||
|
|
||||||
ulong gpuVa = (uint)qmd.ConstantBufferAddrLower(index) | (ulong)qmd.ConstantBufferAddrUpper(index) << 32;
|
|
||||||
ulong size = (ulong)qmd.ConstantBufferSize(index);
|
|
||||||
|
|
||||||
BufferManager.SetComputeUniformBuffer(index, gpuVa, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int index = 0; index < info.CBuffers.Count; index++)
|
for (int index = 0; index < info.CBuffers.Count; index++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -207,6 +207,17 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
UpdateRenderTargets();
|
UpdateRenderTargets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a texture descriptor used on the compute pipeline.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="handle">Shader "fake" handle of the texture</param>
|
||||||
|
/// <returns>The texture descriptor</returns>
|
||||||
|
public TextureDescriptor GetComputeTextureDescriptor(GpuState state, int handle)
|
||||||
|
{
|
||||||
|
return _cpBindingsManager.GetTextureDescriptor(state, 0, handle);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a texture descriptor used on the graphics pipeline.
|
/// Gets a texture descriptor used on the graphics pipeline.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This automatically translates, compiles and adds the code to the cache if not present.
|
/// This automatically translates, compiles and adds the code to the cache if not present.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
/// <param name="gpuVa">GPU virtual address of the binary shader code</param>
|
/// <param name="gpuVa">GPU virtual address of the binary shader code</param>
|
||||||
/// <param name="localSizeX">Local group size X of the computer shader</param>
|
/// <param name="localSizeX">Local group size X of the computer shader</param>
|
||||||
/// <param name="localSizeY">Local group size Y of the computer shader</param>
|
/// <param name="localSizeY">Local group size Y of the computer shader</param>
|
||||||
|
@ -58,6 +59,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <param name="sharedMemorySize">Shared memory size of the compute shader</param>
|
/// <param name="sharedMemorySize">Shared memory size of the compute shader</param>
|
||||||
/// <returns>Compiled compute shader code</returns>
|
/// <returns>Compiled compute shader code</returns>
|
||||||
public ComputeShader GetComputeShader(
|
public ComputeShader GetComputeShader(
|
||||||
|
GpuState state,
|
||||||
ulong gpuVa,
|
ulong gpuVa,
|
||||||
int localSizeX,
|
int localSizeX,
|
||||||
int localSizeY,
|
int localSizeY,
|
||||||
|
@ -79,6 +81,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedShader shader = TranslateComputeShader(
|
CachedShader shader = TranslateComputeShader(
|
||||||
|
state,
|
||||||
gpuVa,
|
gpuVa,
|
||||||
localSizeX,
|
localSizeX,
|
||||||
localSizeY,
|
localSizeY,
|
||||||
|
@ -241,6 +244,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Translates the binary Maxwell shader code to something that the host API accepts.
|
/// Translates the binary Maxwell shader code to something that the host API accepts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
/// <param name="gpuVa">GPU virtual address of the binary shader code</param>
|
/// <param name="gpuVa">GPU virtual address of the binary shader code</param>
|
||||||
/// <param name="localSizeX">Local group size X of the computer shader</param>
|
/// <param name="localSizeX">Local group size X of the computer shader</param>
|
||||||
/// <param name="localSizeY">Local group size Y of the computer shader</param>
|
/// <param name="localSizeY">Local group size Y of the computer shader</param>
|
||||||
|
@ -249,6 +253,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <param name="sharedMemorySize">Shared memory size of the compute shader</param>
|
/// <param name="sharedMemorySize">Shared memory size of the compute shader</param>
|
||||||
/// <returns>Compiled compute shader code</returns>
|
/// <returns>Compiled compute shader code</returns>
|
||||||
private CachedShader TranslateComputeShader(
|
private CachedShader TranslateComputeShader(
|
||||||
|
GpuState state,
|
||||||
ulong gpuVa,
|
ulong gpuVa,
|
||||||
int localSizeX,
|
int localSizeX,
|
||||||
int localSizeY,
|
int localSizeY,
|
||||||
|
@ -265,12 +270,20 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
{
|
{
|
||||||
return info switch
|
return info switch
|
||||||
{
|
{
|
||||||
QueryInfoName.ComputeLocalSizeX => localSizeX,
|
QueryInfoName.ComputeLocalSizeX
|
||||||
QueryInfoName.ComputeLocalSizeY => localSizeY,
|
=> localSizeX,
|
||||||
QueryInfoName.ComputeLocalSizeZ => localSizeZ,
|
QueryInfoName.ComputeLocalSizeY
|
||||||
QueryInfoName.ComputeLocalMemorySize => localMemorySize,
|
=> localSizeY,
|
||||||
QueryInfoName.ComputeSharedMemorySize => sharedMemorySize,
|
QueryInfoName.ComputeLocalSizeZ
|
||||||
_ => QueryInfoCommon(info)
|
=> localSizeZ,
|
||||||
|
QueryInfoName.ComputeLocalMemorySize
|
||||||
|
=> localMemorySize,
|
||||||
|
QueryInfoName.ComputeSharedMemorySize
|
||||||
|
=> sharedMemorySize,
|
||||||
|
QueryInfoName.TextureFormat
|
||||||
|
=> (int)QueryComputeTextureFormat(state, index),
|
||||||
|
_
|
||||||
|
=> QueryInfoCommon(info)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,10 +330,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
{
|
{
|
||||||
return info switch
|
return info switch
|
||||||
{
|
{
|
||||||
QueryInfoName.IsTextureBuffer => Convert.ToInt32(QueryIsTextureBuffer(state, (int)stage - 1, index)),
|
QueryInfoName.IsTextureBuffer
|
||||||
QueryInfoName.IsTextureRectangle => Convert.ToInt32(QueryIsTextureRectangle(state, (int)stage - 1, index)),
|
=> Convert.ToInt32(QueryIsTextureBuffer(state, (int)stage - 1, index)),
|
||||||
QueryInfoName.PrimitiveTopology => (int)GetPrimitiveTopology(),
|
QueryInfoName.IsTextureRectangle
|
||||||
_ => QueryInfoCommon(info)
|
=> Convert.ToInt32(QueryIsTextureRectangle(state, (int)stage - 1, index)),
|
||||||
|
QueryInfoName.PrimitiveTopology
|
||||||
|
=> (int)QueryPrimitiveTopology(),
|
||||||
|
QueryInfoName.TextureFormat
|
||||||
|
=> (int)QueryGraphicsTextureFormat(state, (int)stage - 1, index),
|
||||||
|
_
|
||||||
|
=> QueryInfoCommon(info)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +397,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// This is required by geometry shaders.
|
/// This is required by geometry shaders.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Primitive topology</returns>
|
/// <returns>Primitive topology</returns>
|
||||||
private InputTopology GetPrimitiveTopology()
|
private InputTopology QueryPrimitiveTopology()
|
||||||
{
|
{
|
||||||
switch (_context.Methods.PrimitiveType)
|
switch (_context.Methods.PrimitiveType)
|
||||||
{
|
{
|
||||||
|
@ -414,7 +433,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <returns>True if the texture is a buffer texture, false otherwise</returns>
|
/// <returns>True if the texture is a buffer texture, false otherwise</returns>
|
||||||
private bool QueryIsTextureBuffer(GpuState state, int stageIndex, int index)
|
private bool QueryIsTextureBuffer(GpuState state, int stageIndex, int index)
|
||||||
{
|
{
|
||||||
return GetTextureDescriptor(state, stageIndex, index).UnpackTextureTarget() == TextureTarget.TextureBuffer;
|
return GetGraphicsTextureDescriptor(state, stageIndex, index).UnpackTextureTarget() == TextureTarget.TextureBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -428,7 +447,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <returns>True if the texture is a rectangle texture, false otherwise</returns>
|
/// <returns>True if the texture is a rectangle texture, false otherwise</returns>
|
||||||
private bool QueryIsTextureRectangle(GpuState state, int stageIndex, int index)
|
private bool QueryIsTextureRectangle(GpuState state, int stageIndex, int index)
|
||||||
{
|
{
|
||||||
var descriptor = GetTextureDescriptor(state, stageIndex, index);
|
var descriptor = GetGraphicsTextureDescriptor(state, stageIndex, index);
|
||||||
|
|
||||||
TextureTarget target = descriptor.UnpackTextureTarget();
|
TextureTarget target = descriptor.UnpackTextureTarget();
|
||||||
|
|
||||||
|
@ -439,15 +458,106 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the texture descriptor for a given texture on the pool.
|
/// Queries the format of a given texture.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="index">Index of the texture (this is the shader "fake" handle)</param>
|
||||||
|
/// <returns>The texture format</returns>
|
||||||
|
private TextureFormat QueryComputeTextureFormat(GpuState state, int index)
|
||||||
|
{
|
||||||
|
return QueryTextureFormat(GetComputeTextureDescriptor(state, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queries the format of a given texture.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">Current GPU state</param>
|
/// <param name="state">Current GPU state</param>
|
||||||
/// <param name="stageIndex">Index of the shader stage</param>
|
/// <param name="stageIndex">Index of the shader stage</param>
|
||||||
/// <param name="index">Index of the texture (this is the shader "fake" handle)</param>
|
/// <param name="index">Index of the texture (this is the shader "fake" handle)</param>
|
||||||
/// <returns>Texture descriptor</returns>
|
/// <returns>The texture format</returns>
|
||||||
private TextureDescriptor GetTextureDescriptor(GpuState state, int stageIndex, int index)
|
private TextureFormat QueryGraphicsTextureFormat(GpuState state, int stageIndex, int index)
|
||||||
{
|
{
|
||||||
return _context.Methods.TextureManager.GetGraphicsTextureDescriptor(state, stageIndex, index);
|
return QueryTextureFormat(GetGraphicsTextureDescriptor(state, stageIndex, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queries the format of a given texture.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="descriptor">Descriptor of the texture from the texture pool</param>
|
||||||
|
/// <returns>The texture format</returns>
|
||||||
|
private static TextureFormat QueryTextureFormat(TextureDescriptor descriptor)
|
||||||
|
{
|
||||||
|
if (!FormatTable.TryGetTextureFormat(descriptor.UnpackFormat(), descriptor.UnpackSrgb(), out FormatInfo formatInfo))
|
||||||
|
{
|
||||||
|
return TextureFormat.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatInfo.Format switch
|
||||||
|
{
|
||||||
|
Format.R8Unorm => TextureFormat.R8Unorm,
|
||||||
|
Format.R8Snorm => TextureFormat.R8Snorm,
|
||||||
|
Format.R8Uint => TextureFormat.R8Uint,
|
||||||
|
Format.R8Sint => TextureFormat.R8Sint,
|
||||||
|
Format.R16Float => TextureFormat.R16Float,
|
||||||
|
Format.R16Unorm => TextureFormat.R16Unorm,
|
||||||
|
Format.R16Snorm => TextureFormat.R16Snorm,
|
||||||
|
Format.R16Uint => TextureFormat.R16Uint,
|
||||||
|
Format.R16Sint => TextureFormat.R16Sint,
|
||||||
|
Format.R32Float => TextureFormat.R32Float,
|
||||||
|
Format.R32Uint => TextureFormat.R32Uint,
|
||||||
|
Format.R32Sint => TextureFormat.R32Sint,
|
||||||
|
Format.R8G8Unorm => TextureFormat.R8G8Unorm,
|
||||||
|
Format.R8G8Snorm => TextureFormat.R8G8Snorm,
|
||||||
|
Format.R8G8Uint => TextureFormat.R8G8Uint,
|
||||||
|
Format.R8G8Sint => TextureFormat.R8G8Sint,
|
||||||
|
Format.R16G16Float => TextureFormat.R16G16Float,
|
||||||
|
Format.R16G16Unorm => TextureFormat.R16G16Unorm,
|
||||||
|
Format.R16G16Snorm => TextureFormat.R16G16Snorm,
|
||||||
|
Format.R16G16Uint => TextureFormat.R16G16Uint,
|
||||||
|
Format.R16G16Sint => TextureFormat.R16G16Sint,
|
||||||
|
Format.R32G32Float => TextureFormat.R32G32Float,
|
||||||
|
Format.R32G32Uint => TextureFormat.R32G32Uint,
|
||||||
|
Format.R32G32Sint => TextureFormat.R32G32Sint,
|
||||||
|
Format.R8G8B8A8Unorm => TextureFormat.R8G8B8A8Unorm,
|
||||||
|
Format.R8G8B8A8Snorm => TextureFormat.R8G8B8A8Snorm,
|
||||||
|
Format.R8G8B8A8Uint => TextureFormat.R8G8B8A8Uint,
|
||||||
|
Format.R8G8B8A8Sint => TextureFormat.R8G8B8A8Sint,
|
||||||
|
Format.R16G16B16A16Float => TextureFormat.R16G16B16A16Float,
|
||||||
|
Format.R16G16B16A16Unorm => TextureFormat.R16G16B16A16Unorm,
|
||||||
|
Format.R16G16B16A16Snorm => TextureFormat.R16G16B16A16Snorm,
|
||||||
|
Format.R16G16B16A16Uint => TextureFormat.R16G16B16A16Uint,
|
||||||
|
Format.R16G16B16A16Sint => TextureFormat.R16G16B16A16Sint,
|
||||||
|
Format.R32G32B32A32Float => TextureFormat.R32G32B32A32Float,
|
||||||
|
Format.R32G32B32A32Uint => TextureFormat.R32G32B32A32Uint,
|
||||||
|
Format.R32G32B32A32Sint => TextureFormat.R32G32B32A32Sint,
|
||||||
|
Format.R10G10B10A2Unorm => TextureFormat.R10G10B10A2Unorm,
|
||||||
|
Format.R10G10B10A2Uint => TextureFormat.R10G10B10A2Uint,
|
||||||
|
Format.R11G11B10Float => TextureFormat.R11G11B10Float,
|
||||||
|
_ => TextureFormat.Unknown
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the texture descriptor for a given texture on the pool.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="handle">Index of the texture (this is the shader "fake" handle)</param>
|
||||||
|
/// <returns>Texture descriptor</returns>
|
||||||
|
private TextureDescriptor GetComputeTextureDescriptor(GpuState state, int handle)
|
||||||
|
{
|
||||||
|
return _context.Methods.TextureManager.GetComputeTextureDescriptor(state, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the texture descriptor for a given texture on the pool.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">Current GPU state</param>
|
||||||
|
/// <param name="stageIndex">Index of the shader stage</param>
|
||||||
|
/// <param name="handle">Index of the texture (this is the shader "fake" handle)</param>
|
||||||
|
/// <returns>Texture descriptor</returns>
|
||||||
|
private TextureDescriptor GetGraphicsTextureDescriptor(GpuState state, int stageIndex, int handle)
|
||||||
|
{
|
||||||
|
return _context.Methods.TextureManager.GetGraphicsTextureDescriptor(state, stageIndex, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -459,9 +569,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
{
|
{
|
||||||
return info switch
|
return info switch
|
||||||
{
|
{
|
||||||
QueryInfoName.StorageBufferOffsetAlignment => _context.Capabilities.StorageBufferOffsetAlignment,
|
QueryInfoName.StorageBufferOffsetAlignment
|
||||||
QueryInfoName.SupportsNonConstantTextureOffset => Convert.ToInt32(_context.Capabilities.SupportsNonConstantTextureOffset),
|
=> _context.Capabilities.StorageBufferOffsetAlignment,
|
||||||
_ => 0
|
QueryInfoName.SupportsNonConstantTextureOffset
|
||||||
|
=> Convert.ToInt32(_context.Capabilities.SupportsNonConstantTextureOffset),
|
||||||
|
_
|
||||||
|
=> 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -326,9 +326,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
string imageTypeName = GetImageTypeName(texOp.Type);
|
string layout = texOp.Format.ToGlslFormat();
|
||||||
|
|
||||||
context.AppendLine("writeonly uniform " + imageTypeName + " " + imageName + ";");
|
if (!string.IsNullOrEmpty(layout))
|
||||||
|
{
|
||||||
|
layout = "layout(" + layout + ") ";
|
||||||
|
}
|
||||||
|
|
||||||
|
string imageTypeName = GetImageTypeName(texOp.Type, texOp.Format.GetComponentType());
|
||||||
|
|
||||||
|
context.AppendLine("uniform " + layout + imageTypeName + " " + imageName + ";");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (KeyValuePair<string, AstTextureOperation> kv in images)
|
foreach (KeyValuePair<string, AstTextureOperation> kv in images)
|
||||||
|
@ -455,7 +462,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
return typeName;
|
return typeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetImageTypeName(SamplerType type)
|
private static string GetImageTypeName(SamplerType type, VariableType componentType)
|
||||||
{
|
{
|
||||||
string typeName;
|
string typeName;
|
||||||
|
|
||||||
|
@ -480,6 +487,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
typeName += "Array";
|
typeName += "Array";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (componentType)
|
||||||
|
{
|
||||||
|
case VariableType.U32: typeName = 'u' + typeName; break;
|
||||||
|
case VariableType.S32: typeName = 'i' + typeName; break;
|
||||||
|
}
|
||||||
|
|
||||||
return typeName;
|
return typeName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
|
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
|
||||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenMemory;
|
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenMemory;
|
||||||
|
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenPacking;
|
||||||
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
|
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
|
@ -115,53 +116,56 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
{
|
{
|
||||||
switch (inst)
|
switch (inst)
|
||||||
{
|
{
|
||||||
|
case Instruction.ImageLoad:
|
||||||
|
return ImageLoadOrStore(context, operation);
|
||||||
|
|
||||||
case Instruction.ImageStore:
|
case Instruction.ImageStore:
|
||||||
return InstGenMemory.ImageStore(context, operation);
|
return ImageLoadOrStore(context, operation);
|
||||||
|
|
||||||
case Instruction.LoadAttribute:
|
case Instruction.LoadAttribute:
|
||||||
return InstGenMemory.LoadAttribute(context, operation);
|
return LoadAttribute(context, operation);
|
||||||
|
|
||||||
case Instruction.LoadConstant:
|
case Instruction.LoadConstant:
|
||||||
return InstGenMemory.LoadConstant(context, operation);
|
return LoadConstant(context, operation);
|
||||||
|
|
||||||
case Instruction.LoadLocal:
|
case Instruction.LoadLocal:
|
||||||
return InstGenMemory.LoadLocal(context, operation);
|
return LoadLocal(context, operation);
|
||||||
|
|
||||||
case Instruction.LoadShared:
|
case Instruction.LoadShared:
|
||||||
return InstGenMemory.LoadShared(context, operation);
|
return LoadShared(context, operation);
|
||||||
|
|
||||||
case Instruction.LoadStorage:
|
case Instruction.LoadStorage:
|
||||||
return InstGenMemory.LoadStorage(context, operation);
|
return LoadStorage(context, operation);
|
||||||
|
|
||||||
case Instruction.Lod:
|
case Instruction.Lod:
|
||||||
return InstGenMemory.Lod(context, operation);
|
return Lod(context, operation);
|
||||||
|
|
||||||
case Instruction.PackDouble2x32:
|
case Instruction.PackDouble2x32:
|
||||||
return InstGenPacking.PackDouble2x32(context, operation);
|
return PackDouble2x32(context, operation);
|
||||||
|
|
||||||
case Instruction.PackHalf2x16:
|
case Instruction.PackHalf2x16:
|
||||||
return InstGenPacking.PackHalf2x16(context, operation);
|
return PackHalf2x16(context, operation);
|
||||||
|
|
||||||
case Instruction.StoreLocal:
|
case Instruction.StoreLocal:
|
||||||
return InstGenMemory.StoreLocal(context, operation);
|
return StoreLocal(context, operation);
|
||||||
|
|
||||||
case Instruction.StoreShared:
|
case Instruction.StoreShared:
|
||||||
return InstGenMemory.StoreShared(context, operation);
|
return StoreShared(context, operation);
|
||||||
|
|
||||||
case Instruction.StoreStorage:
|
case Instruction.StoreStorage:
|
||||||
return InstGenMemory.StoreStorage(context, operation);
|
return StoreStorage(context, operation);
|
||||||
|
|
||||||
case Instruction.TextureSample:
|
case Instruction.TextureSample:
|
||||||
return InstGenMemory.TextureSample(context, operation);
|
return TextureSample(context, operation);
|
||||||
|
|
||||||
case Instruction.TextureSize:
|
case Instruction.TextureSize:
|
||||||
return InstGenMemory.TextureSize(context, operation);
|
return TextureSize(context, operation);
|
||||||
|
|
||||||
case Instruction.UnpackDouble2x32:
|
case Instruction.UnpackDouble2x32:
|
||||||
return InstGenPacking.UnpackDouble2x32(context, operation);
|
return UnpackDouble2x32(context, operation);
|
||||||
|
|
||||||
case Instruction.UnpackHalf2x16:
|
case Instruction.UnpackHalf2x16:
|
||||||
return InstGenPacking.UnpackHalf2x16(context, operation);
|
return UnpackHalf2x16(context, operation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
{
|
{
|
||||||
static class InstGenMemory
|
static class InstGenMemory
|
||||||
{
|
{
|
||||||
public static string ImageStore(CodeGenContext context, AstOperation operation)
|
public static string ImageLoadOrStore(CodeGenContext context, AstOperation operation)
|
||||||
{
|
{
|
||||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||||
|
|
||||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||||
|
|
||||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||||
|
|
||||||
string texCall = "imageStore";
|
string texCall = texOp.Inst == Instruction.ImageLoad ? "imageLoad" : "imageStore";
|
||||||
|
|
||||||
int srcIndex = isBindless ? 1 : 0;
|
int srcIndex = isBindless ? 1 : 0;
|
||||||
|
|
||||||
|
@ -40,14 +40,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
|
|
||||||
int coordsCount = texOp.Type.GetDimensions();
|
int coordsCount = texOp.Type.GetDimensions();
|
||||||
|
|
||||||
int pCount = coordsCount;
|
int pCount = coordsCount + (isArray ? 1 : 0);
|
||||||
|
|
||||||
int arrayIndexElem = -1;
|
|
||||||
|
|
||||||
if (isArray)
|
|
||||||
{
|
|
||||||
arrayIndexElem = pCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Append(string str)
|
void Append(string str)
|
||||||
{
|
{
|
||||||
|
@ -70,23 +63,40 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
Append(Src(VariableType.S32));
|
Append(Src(VariableType.S32));
|
||||||
}
|
}
|
||||||
|
|
||||||
string[] cElems = new string[4];
|
if (texOp.Inst == Instruction.ImageStore)
|
||||||
|
|
||||||
for (int index = 0; index < 4; index++)
|
|
||||||
{
|
{
|
||||||
if (srcIndex < texOp.SourcesCount)
|
VariableType type = texOp.Format.GetComponentType();
|
||||||
|
|
||||||
|
string[] cElems = new string[4];
|
||||||
|
|
||||||
|
for (int index = 0; index < 4; index++)
|
||||||
{
|
{
|
||||||
cElems[index] = Src(VariableType.F32);
|
if (srcIndex < texOp.SourcesCount)
|
||||||
|
{
|
||||||
|
cElems[index] = Src(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cElems[index] = type switch
|
||||||
|
{
|
||||||
|
VariableType.S32 => NumberFormatter.FormatInt(0),
|
||||||
|
VariableType.U32 => NumberFormatter.FormatUint(0),
|
||||||
|
_ => NumberFormatter.FormatFloat(0)
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
string prefix = type switch
|
||||||
{
|
{
|
||||||
cElems[index] = NumberFormatter.FormatFloat(0);
|
VariableType.S32 => "i",
|
||||||
}
|
VariableType.U32 => "u",
|
||||||
|
_ => string.Empty
|
||||||
|
};
|
||||||
|
|
||||||
|
Append(prefix + "vec4(" + string.Join(", ", cElems) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
Append("vec4(" + string.Join(", ", cElems) + ")");
|
texCall += ")" + (texOp.Inst == Instruction.ImageLoad ? GetMask(texOp.Index) : "");
|
||||||
|
|
||||||
texCall += ")";
|
|
||||||
|
|
||||||
return texCall;
|
return texCall;
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,6 +280,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
{
|
{
|
||||||
return GetOperandVarType((AstOperand)operation.GetSource(0));
|
return GetOperandVarType((AstOperand)operation.GetSource(0));
|
||||||
}
|
}
|
||||||
|
else if (operation is AstTextureOperation texOp &&
|
||||||
|
(texOp.Inst == Instruction.ImageLoad ||
|
||||||
|
texOp.Inst == Instruction.ImageStore))
|
||||||
|
{
|
||||||
|
return texOp.Format.GetComponentType();
|
||||||
|
}
|
||||||
|
|
||||||
return GetDestVarType(operation.Inst);
|
return GetDestVarType(operation.Inst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,6 +219,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
Set("1110111101010x", InstEmit.St, typeof(OpCodeMemory));
|
Set("1110111101010x", InstEmit.St, typeof(OpCodeMemory));
|
||||||
Set("1110111011011x", InstEmit.Stg, typeof(OpCodeMemory));
|
Set("1110111011011x", InstEmit.Stg, typeof(OpCodeMemory));
|
||||||
Set("1110111101011x", InstEmit.Sts, typeof(OpCodeMemory));
|
Set("1110111101011x", InstEmit.Sts, typeof(OpCodeMemory));
|
||||||
|
Set("11101011000xxx", InstEmit.Suld, typeof(OpCodeImage));
|
||||||
Set("11101011001xxx", InstEmit.Sust, typeof(OpCodeImage));
|
Set("11101011001xxx", InstEmit.Sust, typeof(OpCodeImage));
|
||||||
Set("1111000011111x", InstEmit.Sync, typeof(OpCodeBranchPop));
|
Set("1111000011111x", InstEmit.Sync, typeof(OpCodeBranchPop));
|
||||||
Set("110000xxxx111x", InstEmit.Tex, typeof(OpCodeTex));
|
Set("110000xxxx111x", InstEmit.Tex, typeof(OpCodeTex));
|
||||||
|
|
|
@ -4,12 +4,152 @@ using Ryujinx.Graphics.Shader.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.Instructions
|
namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
{
|
{
|
||||||
static partial class InstEmit
|
static partial class InstEmit
|
||||||
{
|
{
|
||||||
|
public static void Suld(EmitterContext context)
|
||||||
|
{
|
||||||
|
OpCodeImage op = (OpCodeImage)context.CurrOp;
|
||||||
|
|
||||||
|
SamplerType type = ConvertSamplerType(op.Dimensions);
|
||||||
|
|
||||||
|
if (type == SamplerType.None)
|
||||||
|
{
|
||||||
|
context.Config.PrintLog("Invalid image store sampler type.");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rb is Rd on the SULD instruction.
|
||||||
|
int rdIndex = op.Rb.Index;
|
||||||
|
int raIndex = op.Ra.Index;
|
||||||
|
|
||||||
|
Operand Ra()
|
||||||
|
{
|
||||||
|
if (raIndex > RegisterConsts.RegisterZeroIndex)
|
||||||
|
{
|
||||||
|
return Const(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.Copy(Register(raIndex++, RegisterType.Gpr));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isArray = op.Dimensions == ImageDimensions.Image1DArray ||
|
||||||
|
op.Dimensions == ImageDimensions.Image2DArray;
|
||||||
|
|
||||||
|
Operand arrayIndex = isArray ? Ra() : null;
|
||||||
|
|
||||||
|
List<Operand> sourcesList = new List<Operand>();
|
||||||
|
|
||||||
|
if (op.IsBindless)
|
||||||
|
{
|
||||||
|
sourcesList.Add(context.Copy(Register(op.Rc)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int coordsCount = type.GetDimensions();
|
||||||
|
|
||||||
|
for (int index = 0; index < coordsCount; index++)
|
||||||
|
{
|
||||||
|
sourcesList.Add(Ra());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isArray)
|
||||||
|
{
|
||||||
|
sourcesList.Add(arrayIndex);
|
||||||
|
|
||||||
|
type |= SamplerType.Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand[] sources = sourcesList.ToArray();
|
||||||
|
|
||||||
|
int handle = !op.IsBindless ? op.Immediate : 0;
|
||||||
|
|
||||||
|
TextureFlags flags = op.IsBindless ? TextureFlags.Bindless : TextureFlags.None;
|
||||||
|
|
||||||
|
if (op.UseComponents)
|
||||||
|
{
|
||||||
|
int componentMask = (int)op.Components;
|
||||||
|
|
||||||
|
for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
|
||||||
|
{
|
||||||
|
if ((compMask & 1) == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rdIndex == RegisterConsts.RegisterZeroIndex)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand rd = Register(rdIndex++, RegisterType.Gpr);
|
||||||
|
|
||||||
|
TextureOperation operation = new TextureOperation(
|
||||||
|
Instruction.ImageLoad,
|
||||||
|
type,
|
||||||
|
flags,
|
||||||
|
handle,
|
||||||
|
compIndex,
|
||||||
|
rd,
|
||||||
|
sources);
|
||||||
|
|
||||||
|
if (!op.IsBindless)
|
||||||
|
{
|
||||||
|
operation.Format = GetTextureFormat(context, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Add(operation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (op.ByteAddress)
|
||||||
|
{
|
||||||
|
int xIndex = op.IsBindless ? 1 : 0;
|
||||||
|
|
||||||
|
sources[xIndex] = context.ShiftRightS32(sources[xIndex], Const(GetComponentSizeInBytesLog2(op.Size)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int components = GetComponents(op.Size);
|
||||||
|
|
||||||
|
for (int compIndex = 0; compIndex < components; compIndex++)
|
||||||
|
{
|
||||||
|
if (rdIndex == RegisterConsts.RegisterZeroIndex)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand rd = Register(rdIndex++, RegisterType.Gpr);
|
||||||
|
|
||||||
|
TextureOperation operation = new TextureOperation(
|
||||||
|
Instruction.ImageLoad,
|
||||||
|
type,
|
||||||
|
flags,
|
||||||
|
handle,
|
||||||
|
compIndex,
|
||||||
|
rd,
|
||||||
|
sources)
|
||||||
|
{
|
||||||
|
Format = GetTextureFormat(op.Size)
|
||||||
|
};
|
||||||
|
|
||||||
|
context.Add(operation);
|
||||||
|
|
||||||
|
switch (op.Size)
|
||||||
|
{
|
||||||
|
case IntegerSize.U8: context.Copy(rd, ZeroExtendTo32(context, rd, 8)); break;
|
||||||
|
case IntegerSize.U16: context.Copy(rd, ZeroExtendTo32(context, rd, 16)); break;
|
||||||
|
case IntegerSize.S8: context.Copy(rd, SignExtendTo32(context, rd, 8)); break;
|
||||||
|
case IntegerSize.S16: context.Copy(rd, SignExtendTo32(context, rd, 16)); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void Sust(EmitterContext context)
|
public static void Sust(EmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeImage op = (OpCodeImage)context.CurrOp;
|
OpCodeImage op = (OpCodeImage)context.CurrOp;
|
||||||
|
@ -72,6 +212,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
type |= SamplerType.Array;
|
type |= SamplerType.Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextureFormat format = TextureFormat.Unknown;
|
||||||
|
|
||||||
if (op.UseComponents)
|
if (op.UseComponents)
|
||||||
{
|
{
|
||||||
int componentMask = (int)op.Components;
|
int componentMask = (int)op.Components;
|
||||||
|
@ -83,12 +225,33 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
sourcesList.Add(Rb());
|
sourcesList.Add(Rb());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!op.IsBindless)
|
||||||
|
{
|
||||||
|
format = GetTextureFormat(context, op.Immediate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Config.PrintLog("Unsized image store not supported.");
|
if (op.ByteAddress)
|
||||||
|
{
|
||||||
|
int xIndex = op.IsBindless ? 1 : 0;
|
||||||
|
|
||||||
|
sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(op.Size)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int components = GetComponents(op.Size);
|
||||||
|
|
||||||
|
for (int compIndex = 0; compIndex < components; compIndex++)
|
||||||
|
{
|
||||||
|
sourcesList.Add(Rb());
|
||||||
|
}
|
||||||
|
|
||||||
|
format = GetTextureFormat(op.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.Console.WriteLine(format.ToString());
|
||||||
|
|
||||||
Operand[] sources = sourcesList.ToArray();
|
Operand[] sources = sourcesList.ToArray();
|
||||||
|
|
||||||
int handle = !op.IsBindless ? op.Immediate : 0;
|
int handle = !op.IsBindless ? op.Immediate : 0;
|
||||||
|
@ -102,7 +265,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
handle,
|
handle,
|
||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
sources);
|
sources)
|
||||||
|
{
|
||||||
|
Format = format
|
||||||
|
};
|
||||||
|
|
||||||
context.Add(operation);
|
context.Add(operation);
|
||||||
}
|
}
|
||||||
|
@ -880,43 +1046,87 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SamplerType ConvertSamplerType(ImageDimensions target)
|
private static int GetComponents(IntegerSize size)
|
||||||
{
|
{
|
||||||
switch (target)
|
return size switch
|
||||||
{
|
{
|
||||||
case ImageDimensions.Image1D:
|
IntegerSize.B64 => 2,
|
||||||
return SamplerType.Texture1D;
|
IntegerSize.B128 => 4,
|
||||||
|
IntegerSize.UB128 => 4,
|
||||||
|
_ => 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case ImageDimensions.ImageBuffer:
|
private static int GetComponentSizeInBytesLog2(IntegerSize size)
|
||||||
return SamplerType.TextureBuffer;
|
{
|
||||||
|
return size switch
|
||||||
|
{
|
||||||
|
IntegerSize.U8 => 0,
|
||||||
|
IntegerSize.S8 => 0,
|
||||||
|
IntegerSize.U16 => 1,
|
||||||
|
IntegerSize.S16 => 1,
|
||||||
|
IntegerSize.B32 => 2,
|
||||||
|
IntegerSize.B64 => 3,
|
||||||
|
IntegerSize.B128 => 4,
|
||||||
|
IntegerSize.UB128 => 4,
|
||||||
|
_ => 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case ImageDimensions.Image1DArray:
|
private static TextureFormat GetTextureFormat(EmitterContext context, int handle)
|
||||||
return SamplerType.Texture1D | SamplerType.Array;
|
{
|
||||||
|
var format = (TextureFormat)context.Config.QueryInfo(QueryInfoName.TextureFormat, handle);
|
||||||
|
|
||||||
case ImageDimensions.Image2D:
|
if (format == TextureFormat.Unknown)
|
||||||
return SamplerType.Texture2D;
|
{
|
||||||
|
context.Config.PrintLog($"Unknown format for texture {handle}.");
|
||||||
|
|
||||||
case ImageDimensions.Image2DArray:
|
format = TextureFormat.R8G8B8A8Unorm;
|
||||||
return SamplerType.Texture2D | SamplerType.Array;
|
|
||||||
|
|
||||||
case ImageDimensions.Image3D:
|
|
||||||
return SamplerType.Texture3D;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SamplerType.None;
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TextureFormat GetTextureFormat(IntegerSize size)
|
||||||
|
{
|
||||||
|
return size switch
|
||||||
|
{
|
||||||
|
IntegerSize.U8 => TextureFormat.R8Uint,
|
||||||
|
IntegerSize.S8 => TextureFormat.R8Sint,
|
||||||
|
IntegerSize.U16 => TextureFormat.R16Uint,
|
||||||
|
IntegerSize.S16 => TextureFormat.R16Sint,
|
||||||
|
IntegerSize.B32 => TextureFormat.R32Uint,
|
||||||
|
IntegerSize.B64 => TextureFormat.R32G32Uint,
|
||||||
|
IntegerSize.B128 => TextureFormat.R32G32B32A32Uint,
|
||||||
|
IntegerSize.UB128 => TextureFormat.R32G32B32A32Uint,
|
||||||
|
_ => TextureFormat.R32Uint
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SamplerType ConvertSamplerType(ImageDimensions target)
|
||||||
|
{
|
||||||
|
return target switch
|
||||||
|
{
|
||||||
|
ImageDimensions.Image1D => SamplerType.Texture1D,
|
||||||
|
ImageDimensions.ImageBuffer => SamplerType.TextureBuffer,
|
||||||
|
ImageDimensions.Image1DArray => SamplerType.Texture1D | SamplerType.Array,
|
||||||
|
ImageDimensions.Image2D => SamplerType.Texture2D,
|
||||||
|
ImageDimensions.Image2DArray => SamplerType.Texture2D | SamplerType.Array,
|
||||||
|
ImageDimensions.Image3D => SamplerType.Texture3D,
|
||||||
|
_ => SamplerType.None
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SamplerType ConvertSamplerType(TextureDimensions dimensions)
|
private static SamplerType ConvertSamplerType(TextureDimensions dimensions)
|
||||||
{
|
{
|
||||||
switch (dimensions)
|
return dimensions switch
|
||||||
{
|
{
|
||||||
case TextureDimensions.Texture1D: return SamplerType.Texture1D;
|
TextureDimensions.Texture1D => SamplerType.Texture1D,
|
||||||
case TextureDimensions.Texture2D: return SamplerType.Texture2D;
|
TextureDimensions.Texture2D => SamplerType.Texture2D,
|
||||||
case TextureDimensions.Texture3D: return SamplerType.Texture3D;
|
TextureDimensions.Texture3D => SamplerType.Texture3D,
|
||||||
case TextureDimensions.TextureCube: return SamplerType.TextureCube;
|
TextureDimensions.TextureCube => SamplerType.TextureCube,
|
||||||
}
|
_ => throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\".")
|
||||||
|
};
|
||||||
throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\".");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SamplerType ConvertSamplerType(TextureTarget type)
|
private static SamplerType ConvertSamplerType(TextureTarget type)
|
||||||
|
|
|
@ -7,6 +7,8 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||||
|
|
||||||
public int Handle { get; private set; }
|
public int Handle { get; private set; }
|
||||||
|
|
||||||
|
public TextureFormat Format { get; set; }
|
||||||
|
|
||||||
public TextureOperation(
|
public TextureOperation(
|
||||||
Instruction inst,
|
Instruction inst,
|
||||||
SamplerType type,
|
SamplerType type,
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace Ryujinx.Graphics.Shader
|
||||||
IsTextureRectangle,
|
IsTextureRectangle,
|
||||||
PrimitiveTopology,
|
PrimitiveTopology,
|
||||||
StorageBufferOffsetAlignment,
|
StorageBufferOffsetAlignment,
|
||||||
SupportsNonConstantTextureOffset
|
SupportsNonConstantTextureOffset,
|
||||||
|
TextureFormat
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,8 +4,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
{
|
{
|
||||||
class AstTextureOperation : AstOperation
|
class AstTextureOperation : AstOperation
|
||||||
{
|
{
|
||||||
public SamplerType Type { get; }
|
public SamplerType Type { get; }
|
||||||
public TextureFlags Flags { get; }
|
public TextureFormat Format { get; }
|
||||||
|
public TextureFlags Flags { get; }
|
||||||
|
|
||||||
public int Handle { get; }
|
public int Handle { get; }
|
||||||
public int ArraySize { get; }
|
public int ArraySize { get; }
|
||||||
|
@ -13,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
public AstTextureOperation(
|
public AstTextureOperation(
|
||||||
Instruction inst,
|
Instruction inst,
|
||||||
SamplerType type,
|
SamplerType type,
|
||||||
|
TextureFormat format,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
int handle,
|
int handle,
|
||||||
int arraySize,
|
int arraySize,
|
||||||
|
@ -20,6 +22,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
params IAstNode[] sources) : base(inst, index, sources)
|
params IAstNode[] sources) : base(inst, index, sources)
|
||||||
{
|
{
|
||||||
Type = type;
|
Type = type;
|
||||||
|
Format = format;
|
||||||
Flags = flags;
|
Flags = flags;
|
||||||
Handle = handle;
|
Handle = handle;
|
||||||
ArraySize = arraySize;
|
ArraySize = arraySize;
|
||||||
|
|
|
@ -57,6 +57,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
return new AstTextureOperation(
|
return new AstTextureOperation(
|
||||||
inst,
|
inst,
|
||||||
texOp.Type,
|
texOp.Type,
|
||||||
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
texOp.Handle,
|
texOp.Handle,
|
||||||
4, // TODO: Non-hardcoded array size.
|
4, // TODO: Non-hardcoded array size.
|
||||||
|
@ -118,6 +119,11 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
|
|
||||||
if (operation is TextureOperation texOp)
|
if (operation is TextureOperation texOp)
|
||||||
{
|
{
|
||||||
|
if (texOp.Inst == Instruction.ImageLoad || texOp.Inst == Instruction.ImageStore)
|
||||||
|
{
|
||||||
|
dest.VarType = texOp.Format.GetComponentType();
|
||||||
|
}
|
||||||
|
|
||||||
AstTextureOperation astTexOp = GetAstTextureOperation(texOp);
|
AstTextureOperation astTexOp = GetAstTextureOperation(texOp);
|
||||||
|
|
||||||
if (texOp.Inst == Instruction.ImageLoad)
|
if (texOp.Inst == Instruction.ImageLoad)
|
||||||
|
|
128
Ryujinx.Graphics.Shader/TextureFormat.cs
Normal file
128
Ryujinx.Graphics.Shader/TextureFormat.cs
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Shader
|
||||||
|
{
|
||||||
|
public enum TextureFormat
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
R8Unorm,
|
||||||
|
R8Snorm,
|
||||||
|
R8Uint,
|
||||||
|
R8Sint,
|
||||||
|
R16Float,
|
||||||
|
R16Unorm,
|
||||||
|
R16Snorm,
|
||||||
|
R16Uint,
|
||||||
|
R16Sint,
|
||||||
|
R32Float,
|
||||||
|
R32Uint,
|
||||||
|
R32Sint,
|
||||||
|
R8G8Unorm,
|
||||||
|
R8G8Snorm,
|
||||||
|
R8G8Uint,
|
||||||
|
R8G8Sint,
|
||||||
|
R16G16Float,
|
||||||
|
R16G16Unorm,
|
||||||
|
R16G16Snorm,
|
||||||
|
R16G16Uint,
|
||||||
|
R16G16Sint,
|
||||||
|
R32G32Float,
|
||||||
|
R32G32Uint,
|
||||||
|
R32G32Sint,
|
||||||
|
R8G8B8A8Unorm,
|
||||||
|
R8G8B8A8Snorm,
|
||||||
|
R8G8B8A8Uint,
|
||||||
|
R8G8B8A8Sint,
|
||||||
|
R16G16B16A16Float,
|
||||||
|
R16G16B16A16Unorm,
|
||||||
|
R16G16B16A16Snorm,
|
||||||
|
R16G16B16A16Uint,
|
||||||
|
R16G16B16A16Sint,
|
||||||
|
R32G32B32A32Float,
|
||||||
|
R32G32B32A32Uint,
|
||||||
|
R32G32B32A32Sint,
|
||||||
|
R10G10B10A2Unorm,
|
||||||
|
R10G10B10A2Uint,
|
||||||
|
R11G11B10Float
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TextureFormatExtensions
|
||||||
|
{
|
||||||
|
public static string ToGlslFormat(this TextureFormat format)
|
||||||
|
{
|
||||||
|
return format switch
|
||||||
|
{
|
||||||
|
TextureFormat.R8Unorm => "r8",
|
||||||
|
TextureFormat.R8Snorm => "r8_snorm",
|
||||||
|
TextureFormat.R8Uint => "r8ui",
|
||||||
|
TextureFormat.R8Sint => "r8i",
|
||||||
|
TextureFormat.R16Float => "r16f",
|
||||||
|
TextureFormat.R16Unorm => "r16",
|
||||||
|
TextureFormat.R16Snorm => "r16_snorm",
|
||||||
|
TextureFormat.R16Uint => "r16ui",
|
||||||
|
TextureFormat.R16Sint => "r16i",
|
||||||
|
TextureFormat.R32Float => "r32f",
|
||||||
|
TextureFormat.R32Uint => "r32ui",
|
||||||
|
TextureFormat.R32Sint => "r32i",
|
||||||
|
TextureFormat.R8G8Unorm => "rg8",
|
||||||
|
TextureFormat.R8G8Snorm => "rg8_snorm",
|
||||||
|
TextureFormat.R8G8Uint => "rg8ui",
|
||||||
|
TextureFormat.R8G8Sint => "rg8i",
|
||||||
|
TextureFormat.R16G16Float => "rg16f",
|
||||||
|
TextureFormat.R16G16Unorm => "rg16",
|
||||||
|
TextureFormat.R16G16Snorm => "rg16_snorm",
|
||||||
|
TextureFormat.R16G16Uint => "rg16ui",
|
||||||
|
TextureFormat.R16G16Sint => "rg16i",
|
||||||
|
TextureFormat.R32G32Float => "rg32f",
|
||||||
|
TextureFormat.R32G32Uint => "rg32ui",
|
||||||
|
TextureFormat.R32G32Sint => "rg32i",
|
||||||
|
TextureFormat.R8G8B8A8Unorm => "rgba8",
|
||||||
|
TextureFormat.R8G8B8A8Snorm => "rgba8_snorm",
|
||||||
|
TextureFormat.R8G8B8A8Uint => "rgba8ui",
|
||||||
|
TextureFormat.R8G8B8A8Sint => "rgba8i",
|
||||||
|
TextureFormat.R16G16B16A16Float => "rgba16f",
|
||||||
|
TextureFormat.R16G16B16A16Unorm => "rgba16",
|
||||||
|
TextureFormat.R16G16B16A16Snorm => "rgba16_snorm",
|
||||||
|
TextureFormat.R16G16B16A16Uint => "rgba16ui",
|
||||||
|
TextureFormat.R16G16B16A16Sint => "rgba16i",
|
||||||
|
TextureFormat.R32G32B32A32Float => "rgba32f",
|
||||||
|
TextureFormat.R32G32B32A32Uint => "rgba32ui",
|
||||||
|
TextureFormat.R32G32B32A32Sint => "rgba32i",
|
||||||
|
TextureFormat.R10G10B10A2Unorm => "rgb10_a2",
|
||||||
|
TextureFormat.R10G10B10A2Uint => "rgb10_a2ui",
|
||||||
|
TextureFormat.R11G11B10Float => "r11f_g11f_b10f",
|
||||||
|
_ => string.Empty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VariableType GetComponentType(this TextureFormat format)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case TextureFormat.R8Uint:
|
||||||
|
case TextureFormat.R16Uint:
|
||||||
|
case TextureFormat.R32Uint:
|
||||||
|
case TextureFormat.R8G8Uint:
|
||||||
|
case TextureFormat.R16G16Uint:
|
||||||
|
case TextureFormat.R32G32Uint:
|
||||||
|
case TextureFormat.R8G8B8A8Uint:
|
||||||
|
case TextureFormat.R16G16B16A16Uint:
|
||||||
|
case TextureFormat.R32G32B32A32Uint:
|
||||||
|
case TextureFormat.R10G10B10A2Uint:
|
||||||
|
return VariableType.U32;
|
||||||
|
case TextureFormat.R8Sint:
|
||||||
|
case TextureFormat.R16Sint:
|
||||||
|
case TextureFormat.R32Sint:
|
||||||
|
case TextureFormat.R8G8Sint:
|
||||||
|
case TextureFormat.R16G16Sint:
|
||||||
|
case TextureFormat.R32G32Sint:
|
||||||
|
case TextureFormat.R8G8B8A8Sint:
|
||||||
|
case TextureFormat.R16G16B16A16Sint:
|
||||||
|
case TextureFormat.R32G32B32A32Sint:
|
||||||
|
return VariableType.S32;
|
||||||
|
};
|
||||||
|
|
||||||
|
return VariableType.F32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -102,6 +102,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
return 16;
|
return 16;
|
||||||
case QueryInfoName.SupportsNonConstantTextureOffset:
|
case QueryInfoName.SupportsNonConstantTextureOffset:
|
||||||
return Convert.ToInt32(true);
|
return Convert.ToInt32(true);
|
||||||
|
case QueryInfoName.TextureFormat:
|
||||||
|
return (int)TextureFormat.R8G8B8A8Unorm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue