Clone the state & flip viewport vertically (#16)
* implement texture get data * reset all state before blit & clone state * format * support blit regions * implement source region for blit * replace bottom with top * account for 0 size * support image flipping * revert presentation fixes & y flip * revert * flip viewport vertically * switch face winding * comment * use SetBytes for texture clear * implement missing compute builtins * change storage and texture buffer alignment * correct compute builtins * don't use nullable for textures and samplers * remove incorrect texture get data implementation * Cleanup IntPtrs --------- Co-authored-by: Isaac Marovitz <isaacryu@icloud.com>
This commit is contained in:
parent
20b1f6a6ee
commit
1f91c74a95
8 changed files with 91 additions and 69 deletions
|
@ -14,5 +14,7 @@ namespace Ryujinx.Graphics.Metal
|
||||||
public const int MaxVertexAttributes = 16;
|
public const int MaxVertexAttributes = 16;
|
||||||
// TODO: Check this value
|
// TODO: Check this value
|
||||||
public const int MaxVertexLayouts = 16;
|
public const int MaxVertexLayouts = 16;
|
||||||
|
public const int MaxTextures = 31;
|
||||||
|
public const int MaxSamplers = 31;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,11 @@ namespace Ryujinx.Graphics.Metal
|
||||||
public MTLFunction? VertexFunction = null;
|
public MTLFunction? VertexFunction = null;
|
||||||
public MTLFunction? FragmentFunction = null;
|
public MTLFunction? FragmentFunction = null;
|
||||||
|
|
||||||
public Dictionary<ulong, MTLTexture> FragmentTextures = new();
|
public MTLTexture[] FragmentTextures = new MTLTexture[Constants.MaxTextures];
|
||||||
public Dictionary<ulong, MTLSamplerState> FragmentSamplers = new();
|
public MTLSamplerState[] FragmentSamplers = new MTLSamplerState[Constants.MaxSamplers];
|
||||||
|
|
||||||
public Dictionary<ulong, MTLTexture> VertexTextures = new();
|
public MTLTexture[] VertexTextures = new MTLTexture[Constants.MaxTextures];
|
||||||
public Dictionary<ulong, MTLSamplerState> VertexSamplers = new();
|
public MTLSamplerState[] VertexSamplers = new MTLSamplerState[Constants.MaxSamplers];
|
||||||
|
|
||||||
public List<BufferInfo> UniformBuffers = [];
|
public List<BufferInfo> UniformBuffers = [];
|
||||||
public List<BufferInfo> StorageBuffers = [];
|
public List<BufferInfo> StorageBuffers = [];
|
||||||
|
@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Metal
|
||||||
|
|
||||||
public PrimitiveTopology Topology = PrimitiveTopology.Triangles;
|
public PrimitiveTopology Topology = PrimitiveTopology.Triangles;
|
||||||
public MTLCullMode CullMode = MTLCullMode.None;
|
public MTLCullMode CullMode = MTLCullMode.None;
|
||||||
public MTLWinding Winding = MTLWinding.Clockwise;
|
public MTLWinding Winding = MTLWinding.CounterClockwise;
|
||||||
|
|
||||||
public MTLViewport[] Viewports = [];
|
public MTLViewport[] Viewports = [];
|
||||||
public MTLScissorRect[] Scissors = [];
|
public MTLScissorRect[] Scissors = [];
|
||||||
|
@ -64,7 +64,7 @@ namespace Ryujinx.Graphics.Metal
|
||||||
// Changes to attachments take recreation!
|
// Changes to attachments take recreation!
|
||||||
public Texture DepthStencil = default;
|
public Texture DepthStencil = default;
|
||||||
public Texture[] RenderTargets = new Texture[Constants.MaxColorAttachments];
|
public Texture[] RenderTargets = new Texture[Constants.MaxColorAttachments];
|
||||||
public Dictionary<int, BlendDescriptor> BlendDescriptors = new();
|
public BlendDescriptor?[] BlendDescriptors = new BlendDescriptor?[Constants.MaxColorAttachments];
|
||||||
public ColorF BlendColor = new();
|
public ColorF BlendColor = new();
|
||||||
|
|
||||||
public VertexBufferDescriptor[] VertexBuffers = [];
|
public VertexBufferDescriptor[] VertexBuffers = [];
|
||||||
|
@ -74,5 +74,20 @@ namespace Ryujinx.Graphics.Metal
|
||||||
public DirtyFlags Dirty = new();
|
public DirtyFlags Dirty = new();
|
||||||
|
|
||||||
public EncoderState() { }
|
public EncoderState() { }
|
||||||
|
|
||||||
|
public EncoderState Clone()
|
||||||
|
{
|
||||||
|
// Certain state (like viewport and scissor) doesn't need to be cloned, as it is always reacreated when assigned to
|
||||||
|
EncoderState clone = this;
|
||||||
|
clone.FragmentTextures = (MTLTexture[])FragmentTextures.Clone();
|
||||||
|
clone.FragmentSamplers = (MTLSamplerState[])FragmentSamplers.Clone();
|
||||||
|
clone.VertexTextures = (MTLTexture[])VertexTextures.Clone();
|
||||||
|
clone.VertexSamplers = (MTLSamplerState[])VertexSamplers.Clone();
|
||||||
|
clone.BlendDescriptors = (BlendDescriptor?[])BlendDescriptors.Clone();
|
||||||
|
clone.VertexBuffers = (VertexBufferDescriptor[])VertexBuffers.Clone();
|
||||||
|
clone.VertexAttribs = (VertexAttribDescriptor[])VertexAttribs.Clone();
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,16 @@ namespace Ryujinx.Graphics.Metal
|
||||||
_depthStencilCache.Dispose();
|
_depthStencilCache.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly void SaveState()
|
public void SaveState()
|
||||||
{
|
{
|
||||||
_backStates.Push(_currentState);
|
_backStates.Push(_currentState);
|
||||||
|
_currentState = _currentState.Clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveAndResetState()
|
||||||
|
{
|
||||||
|
_backStates.Push(_currentState);
|
||||||
|
_currentState = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RestoreState()
|
public void RestoreState()
|
||||||
|
@ -65,6 +72,9 @@ namespace Ryujinx.Graphics.Metal
|
||||||
SetBuffers(renderCommandEncoder, _currentState.StorageBuffers, true);
|
SetBuffers(renderCommandEncoder, _currentState.StorageBuffers, true);
|
||||||
SetCullMode(renderCommandEncoder);
|
SetCullMode(renderCommandEncoder);
|
||||||
SetFrontFace(renderCommandEncoder);
|
SetFrontFace(renderCommandEncoder);
|
||||||
|
|
||||||
|
// Mark the other state as dirty
|
||||||
|
_currentState.Dirty.MarkAll();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -184,8 +194,9 @@ namespace Ryujinx.Graphics.Metal
|
||||||
pipelineAttachment.SourceRGBBlendFactor = MTLBlendFactor.SourceAlpha;
|
pipelineAttachment.SourceRGBBlendFactor = MTLBlendFactor.SourceAlpha;
|
||||||
pipelineAttachment.DestinationRGBBlendFactor = MTLBlendFactor.OneMinusSourceAlpha;
|
pipelineAttachment.DestinationRGBBlendFactor = MTLBlendFactor.OneMinusSourceAlpha;
|
||||||
|
|
||||||
if (_currentState.BlendDescriptors.TryGetValue(i, out BlendDescriptor blendDescriptor))
|
if (_currentState.BlendDescriptors[i] != null)
|
||||||
{
|
{
|
||||||
|
var blendDescriptor = _currentState.BlendDescriptors[i].Value;
|
||||||
pipelineAttachment.SetBlendingEnabled(blendDescriptor.Enable);
|
pipelineAttachment.SetBlendingEnabled(blendDescriptor.Enable);
|
||||||
pipelineAttachment.AlphaBlendOperation = blendDescriptor.AlphaOp.Convert();
|
pipelineAttachment.AlphaBlendOperation = blendDescriptor.AlphaOp.Convert();
|
||||||
pipelineAttachment.RgbBlendOperation = blendDescriptor.ColorOp.Convert();
|
pipelineAttachment.RgbBlendOperation = blendDescriptor.ColorOp.Convert();
|
||||||
|
@ -469,12 +480,13 @@ namespace Ryujinx.Graphics.Metal
|
||||||
for (int i = 0; i < viewports.Length; i++)
|
for (int i = 0; i < viewports.Length; i++)
|
||||||
{
|
{
|
||||||
var viewport = viewports[i];
|
var viewport = viewports[i];
|
||||||
|
// Y coordinate is inverted
|
||||||
_currentState.Viewports[i] = new MTLViewport
|
_currentState.Viewports[i] = new MTLViewport
|
||||||
{
|
{
|
||||||
originX = viewport.Region.X,
|
originX = viewport.Region.X,
|
||||||
originY = viewport.Region.Y,
|
originY = viewport.Region.Y + viewport.Region.Height,
|
||||||
width = viewport.Region.Width,
|
width = viewport.Region.Width,
|
||||||
height = viewport.Region.Height,
|
height = -viewport.Region.Height,
|
||||||
znear = Clamp(viewport.DepthNear),
|
znear = Clamp(viewport.DepthNear),
|
||||||
zfar = Clamp(viewport.DepthFar)
|
zfar = Clamp(viewport.DepthFar)
|
||||||
};
|
};
|
||||||
|
@ -708,33 +720,41 @@ namespace Ryujinx.Graphics.Metal
|
||||||
renderCommandEncoder.SetFrontFacingWinding(_currentState.Winding);
|
renderCommandEncoder.SetFrontFacingWinding(_currentState.Winding);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetTextureAndSampler(MTLRenderCommandEncoder renderCommandEncoder, ShaderStage stage, Dictionary<ulong, MTLTexture> textures, Dictionary<ulong, MTLSamplerState> samplers)
|
private static void SetTextureAndSampler(MTLRenderCommandEncoder renderCommandEncoder, ShaderStage stage, MTLTexture[] textures, MTLSamplerState[] samplers)
|
||||||
{
|
{
|
||||||
foreach (var texture in textures)
|
for (int i = 0; i < textures.Length; i++)
|
||||||
|
{
|
||||||
|
var texture = textures[i];
|
||||||
|
if (texture != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
switch (stage)
|
switch (stage)
|
||||||
{
|
{
|
||||||
case ShaderStage.Vertex:
|
case ShaderStage.Vertex:
|
||||||
renderCommandEncoder.SetVertexTexture(texture.Value, texture.Key);
|
renderCommandEncoder.SetVertexTexture(texture, (ulong)i);
|
||||||
break;
|
break;
|
||||||
case ShaderStage.Fragment:
|
case ShaderStage.Fragment:
|
||||||
renderCommandEncoder.SetFragmentTexture(texture.Value, texture.Key);
|
renderCommandEncoder.SetFragmentTexture(texture, (ulong)i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var sampler in samplers)
|
for (int i = 0; i < samplers.Length; i++)
|
||||||
|
{
|
||||||
|
var sampler = samplers[i];
|
||||||
|
if (sampler != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
switch (stage)
|
switch (stage)
|
||||||
{
|
{
|
||||||
case ShaderStage.Vertex:
|
case ShaderStage.Vertex:
|
||||||
renderCommandEncoder.SetVertexSamplerState(sampler.Value, sampler.Key);
|
renderCommandEncoder.SetVertexSamplerState(sampler, (ulong)i);
|
||||||
break;
|
break;
|
||||||
case ShaderStage.Fragment:
|
case ShaderStage.Fragment:
|
||||||
renderCommandEncoder.SetFragmentSamplerState(sampler.Value, sampler.Key);
|
renderCommandEncoder.SetFragmentSamplerState(sampler, (ulong)i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,10 +93,11 @@ namespace Ryujinx.Graphics.Metal
|
||||||
|
|
||||||
public static MTLWinding Convert(this FrontFace frontFace)
|
public static MTLWinding Convert(this FrontFace frontFace)
|
||||||
{
|
{
|
||||||
|
// The viewport is flipped vertically, therefore we need to switch the winding order as well
|
||||||
return frontFace switch
|
return frontFace switch
|
||||||
{
|
{
|
||||||
FrontFace.Clockwise => MTLWinding.Clockwise,
|
FrontFace.Clockwise => MTLWinding.CounterClockwise,
|
||||||
FrontFace.CounterClockwise => MTLWinding.CounterClockwise,
|
FrontFace.CounterClockwise => MTLWinding.Clockwise,
|
||||||
_ => LogInvalidAndReturn(frontFace, nameof(FrontFace), MTLWinding.Clockwise)
|
_ => LogInvalidAndReturn(frontFace, nameof(FrontFace), MTLWinding.Clockwise)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,9 @@ using Ryujinx.Common;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
using SharpMetal.Foundation;
|
|
||||||
using SharpMetal.Metal;
|
using SharpMetal.Metal;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Metal
|
namespace Ryujinx.Graphics.Metal
|
||||||
|
@ -70,11 +68,9 @@ namespace Ryujinx.Graphics.Metal
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save current state
|
// Save current state
|
||||||
_pipeline.SaveState();
|
_pipeline.SaveAndResetState();
|
||||||
|
|
||||||
_pipeline.SetProgram(_programColorBlit);
|
_pipeline.SetProgram(_programColorBlit);
|
||||||
_pipeline.SetFaceCulling(false, Face.Front);
|
|
||||||
_pipeline.SetDepthTest(new DepthTestDescriptor(false, false, CompareOp.Always));
|
|
||||||
// Viewport and scissor needs to be set before render pass begin so as not to bind the old ones
|
// Viewport and scissor needs to be set before render pass begin so as not to bind the old ones
|
||||||
_pipeline.SetViewports([]);
|
_pipeline.SetViewports([]);
|
||||||
_pipeline.SetScissors([]);
|
_pipeline.SetScissors([]);
|
||||||
|
@ -93,29 +89,21 @@ namespace Ryujinx.Graphics.Metal
|
||||||
{
|
{
|
||||||
const int ClearColorBufferSize = 16;
|
const int ClearColorBufferSize = 16;
|
||||||
|
|
||||||
var buffer = _device.NewBuffer(ClearColorBufferSize, MTLResourceOptions.ResourceStorageModeManaged);
|
|
||||||
var span = new Span<float>(buffer.Contents.ToPointer(), ClearColorBufferSize);
|
|
||||||
clearColor.CopyTo(span);
|
|
||||||
|
|
||||||
buffer.DidModifyRange(new NSRange
|
|
||||||
{
|
|
||||||
location = 0,
|
|
||||||
length = ClearColorBufferSize
|
|
||||||
});
|
|
||||||
|
|
||||||
var handle = buffer.NativePtr;
|
|
||||||
var range = new BufferRange(Unsafe.As<IntPtr, BufferHandle>(ref handle), 0, ClearColorBufferSize);
|
|
||||||
|
|
||||||
// Save current state
|
// Save current state
|
||||||
_pipeline.SaveState();
|
_pipeline.SaveState();
|
||||||
|
|
||||||
_pipeline.SetUniformBuffers([new BufferAssignment(0, range)]);
|
|
||||||
|
|
||||||
_pipeline.SetProgram(_programsColorClear[index]);
|
_pipeline.SetProgram(_programsColorClear[index]);
|
||||||
|
_pipeline.SetBlendState(index, new BlendDescriptor(false, new ColorF(0f, 0f, 0f, 1f), BlendOp.Add, BlendFactor.One, BlendFactor.Zero, BlendOp.Add, BlendFactor.One, BlendFactor.Zero));
|
||||||
_pipeline.SetFaceCulling(false, Face.Front);
|
_pipeline.SetFaceCulling(false, Face.Front);
|
||||||
_pipeline.SetDepthTest(new DepthTestDescriptor(false, false, CompareOp.Always));
|
_pipeline.SetDepthTest(new DepthTestDescriptor(false, false, CompareOp.Always));
|
||||||
// _pipeline.SetRenderTargetColorMasks([componentMask]);
|
// _pipeline.SetRenderTargetColorMasks([componentMask]);
|
||||||
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
|
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
|
||||||
|
|
||||||
|
fixed (float* ptr = clearColor)
|
||||||
|
{
|
||||||
|
_pipeline.GetOrCreateRenderEncoder().SetFragmentBytes((IntPtr)ptr, ClearColorBufferSize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
_pipeline.Draw(4, 1, 0, 0);
|
_pipeline.Draw(4, 1, 0, 0);
|
||||||
|
|
||||||
// Restore previous state
|
// Restore previous state
|
||||||
|
@ -123,37 +111,25 @@ namespace Ryujinx.Graphics.Metal
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void ClearDepthStencil(
|
public unsafe void ClearDepthStencil(
|
||||||
ReadOnlySpan<float> depthValue,
|
float depthValue,
|
||||||
bool depthMask,
|
bool depthMask,
|
||||||
int stencilValue,
|
int stencilValue,
|
||||||
int stencilMask)
|
int stencilMask)
|
||||||
{
|
{
|
||||||
const int ClearColorBufferSize = 16;
|
const int ClearDepthBufferSize = 4;
|
||||||
|
|
||||||
var buffer = _device.NewBuffer(ClearColorBufferSize, MTLResourceOptions.ResourceStorageModeManaged);
|
IntPtr ptr = new(&depthValue);
|
||||||
var span = new Span<float>(buffer.Contents.ToPointer(), ClearColorBufferSize);
|
|
||||||
depthValue.CopyTo(span);
|
|
||||||
|
|
||||||
buffer.DidModifyRange(new NSRange
|
|
||||||
{
|
|
||||||
location = 0,
|
|
||||||
length = ClearColorBufferSize
|
|
||||||
});
|
|
||||||
|
|
||||||
var handle = buffer.NativePtr;
|
|
||||||
var range = new BufferRange(Unsafe.As<IntPtr, BufferHandle>(ref handle), 0, ClearColorBufferSize);
|
|
||||||
|
|
||||||
// Save current state
|
// Save current state
|
||||||
_pipeline.SaveState();
|
_pipeline.SaveState();
|
||||||
|
|
||||||
_pipeline.SetUniformBuffers([new BufferAssignment(0, range)]);
|
|
||||||
|
|
||||||
_pipeline.SetProgram(_programDepthStencilClear);
|
_pipeline.SetProgram(_programDepthStencilClear);
|
||||||
_pipeline.SetFaceCulling(false, Face.Front);
|
_pipeline.SetFaceCulling(false, Face.Front);
|
||||||
_pipeline.SetDepthTest(new DepthTestDescriptor(false, false, CompareOp.Always));
|
_pipeline.SetDepthTest(new DepthTestDescriptor(false, false, CompareOp.Always));
|
||||||
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
|
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
|
||||||
_pipeline.SetDepthTest(new DepthTestDescriptor(true, depthMask, CompareOp.Always));
|
_pipeline.SetDepthTest(new DepthTestDescriptor(true, depthMask, CompareOp.Always));
|
||||||
// _pipeline.SetStencilTest(CreateStencilTestDescriptor(stencilMask != 0, stencilValue, 0xFF, stencilMask));
|
// _pipeline.SetStencilTest(CreateStencilTestDescriptor(stencilMask != 0, stencilValue, 0xFF, stencilMask));
|
||||||
|
_pipeline.GetOrCreateRenderEncoder().SetFragmentBytes(ptr, ClearDepthBufferSize, 0);
|
||||||
_pipeline.Draw(4, 1, 0, 0);
|
_pipeline.Draw(4, 1, 0, 0);
|
||||||
|
|
||||||
// Restore previous state
|
// Restore previous state
|
||||||
|
|
|
@ -186,8 +186,8 @@ namespace Ryujinx.Graphics.Metal
|
||||||
maximumComputeSharedMemorySize: (int)_device.MaxThreadgroupMemoryLength,
|
maximumComputeSharedMemorySize: (int)_device.MaxThreadgroupMemoryLength,
|
||||||
maximumSupportedAnisotropy: 0,
|
maximumSupportedAnisotropy: 0,
|
||||||
shaderSubgroupSize: 256,
|
shaderSubgroupSize: 256,
|
||||||
storageBufferOffsetAlignment: 0,
|
storageBufferOffsetAlignment: 16,
|
||||||
textureBufferOffsetAlignment: 0,
|
textureBufferOffsetAlignment: 16,
|
||||||
gatherBiasPrecision: 0
|
gatherBiasPrecision: 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,11 @@ namespace Ryujinx.Graphics.Metal
|
||||||
_encoderStateManager.SaveState();
|
_encoderStateManager.SaveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SaveAndResetState()
|
||||||
|
{
|
||||||
|
_encoderStateManager.SaveAndResetState();
|
||||||
|
}
|
||||||
|
|
||||||
public void RestoreState()
|
public void RestoreState()
|
||||||
{
|
{
|
||||||
_encoderStateManager.RestoreState();
|
_encoderStateManager.RestoreState();
|
||||||
|
@ -242,7 +247,7 @@ namespace Ryujinx.Graphics.Metal
|
||||||
|
|
||||||
public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)
|
||||||
{
|
{
|
||||||
_helperShader.ClearDepthStencil([depthValue], depthMask, stencilValue, stencilMask);
|
_helperShader.ClearDepthStencil(depthValue, depthMask, stencilValue, stencilMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CommandBufferBarrier()
|
public void CommandBufferBarrier()
|
||||||
|
|
|
@ -19,18 +19,21 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
|
||||||
{
|
{
|
||||||
IoVariable.BaseInstance => ("base_instance", AggregateType.S32),
|
IoVariable.BaseInstance => ("base_instance", AggregateType.S32),
|
||||||
IoVariable.BaseVertex => ("base_vertex", AggregateType.S32),
|
IoVariable.BaseVertex => ("base_vertex", AggregateType.S32),
|
||||||
|
IoVariable.CtaId => ("threadgroup_position_in_grid", AggregateType.Vector3 | AggregateType.U32),
|
||||||
IoVariable.ClipDistance => ("clip_distance", AggregateType.Array | AggregateType.FP32),
|
IoVariable.ClipDistance => ("clip_distance", AggregateType.Array | AggregateType.FP32),
|
||||||
IoVariable.FragmentOutputColor => ($"out.color{location}", AggregateType.Vector4 | AggregateType.FP32),
|
IoVariable.FragmentOutputColor => ($"out.color{location}", AggregateType.Vector4 | AggregateType.FP32),
|
||||||
IoVariable.FragmentOutputDepth => ("out.depth", AggregateType.FP32),
|
IoVariable.FragmentOutputDepth => ("out.depth", AggregateType.FP32),
|
||||||
IoVariable.FrontFacing => ("front_facing", AggregateType.Bool),
|
IoVariable.FrontFacing => ("front_facing", AggregateType.Bool),
|
||||||
|
IoVariable.GlobalId => ("thread_position_in_grid", AggregateType.Vector3 | AggregateType.U32),
|
||||||
IoVariable.InstanceId => ("instance_id", AggregateType.S32),
|
IoVariable.InstanceId => ("instance_id", AggregateType.S32),
|
||||||
|
IoVariable.InvocationId => ("INVOCATION_ID", AggregateType.S32),
|
||||||
IoVariable.PointCoord => ("point_coord", AggregateType.Vector2),
|
IoVariable.PointCoord => ("point_coord", AggregateType.Vector2),
|
||||||
IoVariable.PointSize => ("out.point_size", AggregateType.FP32),
|
IoVariable.PointSize => ("out.point_size", AggregateType.FP32),
|
||||||
IoVariable.Position => ("out.position", AggregateType.Vector4 | AggregateType.FP32),
|
IoVariable.Position => ("out.position", AggregateType.Vector4 | AggregateType.FP32),
|
||||||
IoVariable.PrimitiveId => ("primitive_id", AggregateType.S32),
|
IoVariable.PrimitiveId => ("primitive_id", AggregateType.S32),
|
||||||
IoVariable.UserDefined => GetUserDefinedVariableName(definitions, location, component, isOutput, isPerPatch),
|
IoVariable.UserDefined => GetUserDefinedVariableName(definitions, location, component, isOutput, isPerPatch),
|
||||||
|
IoVariable.ThreadId => ("thread_position_in_threadgroup", AggregateType.Vector3 | AggregateType.U32),
|
||||||
IoVariable.VertexId => ("vertex_id", AggregateType.S32),
|
IoVariable.VertexId => ("vertex_id", AggregateType.S32),
|
||||||
IoVariable.GlobalId => ("global_id", AggregateType.Vector3 | AggregateType.U32),
|
|
||||||
// gl_VertexIndex does not have a direct equivalent in MSL
|
// gl_VertexIndex does not have a direct equivalent in MSL
|
||||||
IoVariable.VertexIndex => ("vertex_index", AggregateType.U32),
|
IoVariable.VertexIndex => ("vertex_index", AggregateType.U32),
|
||||||
IoVariable.ViewportIndex => ("viewport_array_index", AggregateType.S32),
|
IoVariable.ViewportIndex => ("viewport_array_index", AggregateType.S32),
|
||||||
|
|
Loading…
Reference in a new issue