Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
2c9715acf6 | |||
274af65f69 | |||
4ca78eded5 | |||
6cb6b15612 | |||
2725e40838 |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -33,7 +33,7 @@ jobs:
|
||||
shell: bash
|
||||
|
||||
- name: Create tag
|
||||
uses: actions/github-script@v5
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
github.rest.git.createRef({
|
||||
|
@ -32,7 +32,7 @@
|
||||
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.7.7" />
|
||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.3" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.GtkSharp" Version="3.24.24.59-ryujinx" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.26.3-build25" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
|
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
private const ushort FileFormatVersionMajor = 1;
|
||||
private const ushort FileFormatVersionMinor = 2;
|
||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||
private const uint CodeGenVersion = 4646;
|
||||
private const uint CodeGenVersion = 5031;
|
||||
|
||||
private const string SharedTocFileName = "shared.toc";
|
||||
private const string SharedDataFileName = "shared.data";
|
||||
|
@ -187,27 +187,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
context.Config.GpuAccessor.Log("Shader instruction Longjmp is not implemented.");
|
||||
}
|
||||
|
||||
public static void P2rR(EmitterContext context)
|
||||
{
|
||||
InstP2rR op = context.GetOp<InstP2rR>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction P2rR is not implemented.");
|
||||
}
|
||||
|
||||
public static void P2rI(EmitterContext context)
|
||||
{
|
||||
InstP2rI op = context.GetOp<InstP2rI>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction P2rI is not implemented.");
|
||||
}
|
||||
|
||||
public static void P2rC(EmitterContext context)
|
||||
{
|
||||
InstP2rC op = context.GetOp<InstP2rC>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction P2rC is not implemented.");
|
||||
}
|
||||
|
||||
public static void Pexit(EmitterContext context)
|
||||
{
|
||||
InstPexit op = context.GetOp<InstPexit>();
|
||||
|
@ -209,21 +209,15 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
return context.ICompareNotEqual(context.BitwiseAnd(value, Const(1 << bit)), Const(0));
|
||||
}
|
||||
|
||||
if (ccpr)
|
||||
{
|
||||
// TODO: Support Register to condition code flags copy.
|
||||
context.Config.GpuAccessor.Log("R2P.CC not implemented.");
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = ccpr ? RegisterConsts.FlagsCount : RegisterConsts.PredsCount;
|
||||
RegisterType type = ccpr ? RegisterType.Flag : RegisterType.Predicate;
|
||||
int shift = (int)byteSel * 8;
|
||||
|
||||
for (int bit = 0; bit < RegisterConsts.PredsCount; bit++)
|
||||
for (int bit = 0; bit < count; bit++)
|
||||
{
|
||||
Operand pred = Register(bit, RegisterType.Predicate);
|
||||
Operand res = context.ConditionalSelect(Test(mask, bit), Test(value, bit + shift), pred);
|
||||
context.Copy(pred, res);
|
||||
}
|
||||
Operand flag = Register(bit, type);
|
||||
Operand res = context.ConditionalSelect(Test(mask, bit), Test(value, bit + shift), flag);
|
||||
context.Copy(flag, res);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
using Ryujinx.Graphics.Shader.Decoders;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
@ -50,5 +49,68 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
context.Copy(Register(op.DestPred, RegisterType.Predicate), p0Res);
|
||||
context.Copy(Register(op.DestPredInv, RegisterType.Predicate), p1Res);
|
||||
}
|
||||
|
||||
public static void P2rC(EmitterContext context)
|
||||
{
|
||||
InstP2rC op = context.GetOp<InstP2rC>();
|
||||
|
||||
Operand srcA = GetSrcReg(context, op.SrcA);
|
||||
Operand dest = GetSrcReg(context, op.Dest);
|
||||
Operand mask = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset);
|
||||
|
||||
EmitP2r(context, srcA, dest, mask, op.ByteSel, op.Ccpr);
|
||||
}
|
||||
|
||||
public static void P2rI(EmitterContext context)
|
||||
{
|
||||
InstP2rI op = context.GetOp<InstP2rI>();
|
||||
|
||||
Operand srcA = GetSrcReg(context, op.SrcA);
|
||||
Operand dest = GetSrcReg(context, op.Dest);
|
||||
Operand mask = GetSrcImm(context, op.Imm20);
|
||||
|
||||
EmitP2r(context, srcA, dest, mask, op.ByteSel, op.Ccpr);
|
||||
}
|
||||
|
||||
public static void P2rR(EmitterContext context)
|
||||
{
|
||||
InstP2rR op = context.GetOp<InstP2rR>();
|
||||
|
||||
Operand srcA = GetSrcReg(context, op.SrcA);
|
||||
Operand dest = GetSrcReg(context, op.Dest);
|
||||
Operand mask = GetSrcReg(context, op.SrcB);
|
||||
|
||||
EmitP2r(context, srcA, dest, mask, op.ByteSel, op.Ccpr);
|
||||
}
|
||||
|
||||
private static void EmitP2r(
|
||||
EmitterContext context,
|
||||
Operand srcA,
|
||||
Operand dest,
|
||||
Operand mask,
|
||||
ByteSel byteSel,
|
||||
bool ccpr)
|
||||
{
|
||||
int count = ccpr ? RegisterConsts.FlagsCount : RegisterConsts.PredsCount;
|
||||
int shift = (int)byteSel * 8;
|
||||
mask = context.BitwiseAnd(mask, Const(0xff));
|
||||
|
||||
Operand insert = Const(0);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Operand condition = ccpr
|
||||
? Register(i, RegisterType.Flag)
|
||||
: Register(i, RegisterType.Predicate);
|
||||
|
||||
Operand bit = context.ConditionalSelect(condition, Const(1 << (i + shift)), Const(0));
|
||||
insert = context.BitwiseOr(insert, bit);
|
||||
}
|
||||
|
||||
Operand maskShifted = context.ShiftLeft(mask, Const(shift));
|
||||
Operand masked = context.BitwiseAnd(srcA, context.BitwiseNot(maskShifted));
|
||||
Operand res = context.BitwiseOr(masked, context.BitwiseAnd(insert, maskShifted));
|
||||
|
||||
context.Copy(dest, res);
|
||||
}
|
||||
}
|
||||
}
|
@ -168,5 +168,223 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
return _table[(int)format];
|
||||
}
|
||||
|
||||
public static int GetAttributeFormatSize(VkFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VkFormat.R8Unorm:
|
||||
case VkFormat.R8SNorm:
|
||||
case VkFormat.R8Uint:
|
||||
case VkFormat.R8Sint:
|
||||
case VkFormat.R8Uscaled:
|
||||
case VkFormat.R8Sscaled:
|
||||
return 1;
|
||||
|
||||
case VkFormat.R8G8Unorm:
|
||||
case VkFormat.R8G8SNorm:
|
||||
case VkFormat.R8G8Uint:
|
||||
case VkFormat.R8G8Sint:
|
||||
case VkFormat.R8G8Uscaled:
|
||||
case VkFormat.R8G8Sscaled:
|
||||
case VkFormat.R16Sfloat:
|
||||
case VkFormat.R16Unorm:
|
||||
case VkFormat.R16SNorm:
|
||||
case VkFormat.R16Uint:
|
||||
case VkFormat.R16Sint:
|
||||
case VkFormat.R16Uscaled:
|
||||
case VkFormat.R16Sscaled:
|
||||
return 2;
|
||||
|
||||
case VkFormat.R8G8B8Unorm:
|
||||
case VkFormat.R8G8B8SNorm:
|
||||
case VkFormat.R8G8B8Uint:
|
||||
case VkFormat.R8G8B8Sint:
|
||||
case VkFormat.R8G8B8Uscaled:
|
||||
case VkFormat.R8G8B8Sscaled:
|
||||
return 3;
|
||||
|
||||
case VkFormat.R8G8B8A8Unorm:
|
||||
case VkFormat.R8G8B8A8SNorm:
|
||||
case VkFormat.R8G8B8A8Uint:
|
||||
case VkFormat.R8G8B8A8Sint:
|
||||
case VkFormat.R8G8B8A8Srgb:
|
||||
case VkFormat.R8G8B8A8Uscaled:
|
||||
case VkFormat.R8G8B8A8Sscaled:
|
||||
case VkFormat.B8G8R8A8Unorm:
|
||||
case VkFormat.B8G8R8A8Srgb:
|
||||
case VkFormat.R16G16Sfloat:
|
||||
case VkFormat.R16G16Unorm:
|
||||
case VkFormat.R16G16SNorm:
|
||||
case VkFormat.R16G16Uint:
|
||||
case VkFormat.R16G16Sint:
|
||||
case VkFormat.R16G16Uscaled:
|
||||
case VkFormat.R16G16Sscaled:
|
||||
case VkFormat.R32Sfloat:
|
||||
case VkFormat.R32Uint:
|
||||
case VkFormat.R32Sint:
|
||||
case VkFormat.A2B10G10R10UnormPack32:
|
||||
case VkFormat.A2B10G10R10UintPack32:
|
||||
case VkFormat.B10G11R11UfloatPack32:
|
||||
case VkFormat.E5B9G9R9UfloatPack32:
|
||||
case VkFormat.A2B10G10R10SNormPack32:
|
||||
case VkFormat.A2B10G10R10SintPack32:
|
||||
case VkFormat.A2B10G10R10UscaledPack32:
|
||||
case VkFormat.A2B10G10R10SscaledPack32:
|
||||
return 4;
|
||||
|
||||
case VkFormat.R16G16B16Sfloat:
|
||||
case VkFormat.R16G16B16Unorm:
|
||||
case VkFormat.R16G16B16SNorm:
|
||||
case VkFormat.R16G16B16Uint:
|
||||
case VkFormat.R16G16B16Sint:
|
||||
case VkFormat.R16G16B16Uscaled:
|
||||
case VkFormat.R16G16B16Sscaled:
|
||||
return 6;
|
||||
|
||||
case VkFormat.R16G16B16A16Sfloat:
|
||||
case VkFormat.R16G16B16A16Unorm:
|
||||
case VkFormat.R16G16B16A16SNorm:
|
||||
case VkFormat.R16G16B16A16Uint:
|
||||
case VkFormat.R16G16B16A16Sint:
|
||||
case VkFormat.R16G16B16A16Uscaled:
|
||||
case VkFormat.R16G16B16A16Sscaled:
|
||||
case VkFormat.R32G32Sfloat:
|
||||
case VkFormat.R32G32Uint:
|
||||
case VkFormat.R32G32Sint:
|
||||
return 8;
|
||||
|
||||
case VkFormat.R32G32B32Sfloat:
|
||||
case VkFormat.R32G32B32Uint:
|
||||
case VkFormat.R32G32B32Sint:
|
||||
return 12;
|
||||
|
||||
case VkFormat.R32G32B32A32Sfloat:
|
||||
case VkFormat.R32G32B32A32Uint:
|
||||
case VkFormat.R32G32B32A32Sint:
|
||||
return 16;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static VkFormat DropLastComponent(VkFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VkFormat.R8G8Unorm:
|
||||
return VkFormat.R8Unorm;
|
||||
case VkFormat.R8G8SNorm:
|
||||
return VkFormat.R8SNorm;
|
||||
case VkFormat.R8G8Uint:
|
||||
return VkFormat.R8Uint;
|
||||
case VkFormat.R8G8Sint:
|
||||
return VkFormat.R8Sint;
|
||||
case VkFormat.R8G8Uscaled:
|
||||
return VkFormat.R8Uscaled;
|
||||
case VkFormat.R8G8Sscaled:
|
||||
return VkFormat.R8Sscaled;
|
||||
|
||||
case VkFormat.R8G8B8Unorm:
|
||||
return VkFormat.R8G8Unorm;
|
||||
case VkFormat.R8G8B8SNorm:
|
||||
return VkFormat.R8G8SNorm;
|
||||
case VkFormat.R8G8B8Uint:
|
||||
return VkFormat.R8G8Uint;
|
||||
case VkFormat.R8G8B8Sint:
|
||||
return VkFormat.R8G8Sint;
|
||||
case VkFormat.R8G8B8Uscaled:
|
||||
return VkFormat.R8G8Uscaled;
|
||||
case VkFormat.R8G8B8Sscaled:
|
||||
return VkFormat.R8G8Sscaled;
|
||||
|
||||
case VkFormat.R8G8B8A8Unorm:
|
||||
return VkFormat.R8G8B8Unorm;
|
||||
case VkFormat.R8G8B8A8SNorm:
|
||||
return VkFormat.R8G8B8SNorm;
|
||||
case VkFormat.R8G8B8A8Uint:
|
||||
return VkFormat.R8G8B8Uint;
|
||||
case VkFormat.R8G8B8A8Sint:
|
||||
return VkFormat.R8G8B8Sint;
|
||||
case VkFormat.R8G8B8A8Srgb:
|
||||
return VkFormat.R8G8B8Srgb;
|
||||
case VkFormat.R8G8B8A8Uscaled:
|
||||
return VkFormat.R8G8B8Uscaled;
|
||||
case VkFormat.R8G8B8A8Sscaled:
|
||||
return VkFormat.R8G8B8Sscaled;
|
||||
case VkFormat.B8G8R8A8Unorm:
|
||||
return VkFormat.B8G8R8Unorm;
|
||||
case VkFormat.B8G8R8A8Srgb:
|
||||
return VkFormat.B8G8R8Srgb;
|
||||
|
||||
case VkFormat.R16G16Sfloat:
|
||||
return VkFormat.R16Sfloat;
|
||||
case VkFormat.R16G16Unorm:
|
||||
return VkFormat.R16Unorm;
|
||||
case VkFormat.R16G16SNorm:
|
||||
return VkFormat.R16SNorm;
|
||||
case VkFormat.R16G16Uint:
|
||||
return VkFormat.R16Uint;
|
||||
case VkFormat.R16G16Sint:
|
||||
return VkFormat.R16Sint;
|
||||
case VkFormat.R16G16Uscaled:
|
||||
return VkFormat.R16Uscaled;
|
||||
case VkFormat.R16G16Sscaled:
|
||||
return VkFormat.R16Sscaled;
|
||||
|
||||
case VkFormat.R16G16B16Sfloat:
|
||||
return VkFormat.R16G16Sfloat;
|
||||
case VkFormat.R16G16B16Unorm:
|
||||
return VkFormat.R16G16Unorm;
|
||||
case VkFormat.R16G16B16SNorm:
|
||||
return VkFormat.R16G16SNorm;
|
||||
case VkFormat.R16G16B16Uint:
|
||||
return VkFormat.R16G16Uint;
|
||||
case VkFormat.R16G16B16Sint:
|
||||
return VkFormat.R16G16Sint;
|
||||
case VkFormat.R16G16B16Uscaled:
|
||||
return VkFormat.R16G16Uscaled;
|
||||
case VkFormat.R16G16B16Sscaled:
|
||||
return VkFormat.R16G16Sscaled;
|
||||
|
||||
case VkFormat.R16G16B16A16Sfloat:
|
||||
return VkFormat.R16G16B16Sfloat;
|
||||
case VkFormat.R16G16B16A16Unorm:
|
||||
return VkFormat.R16G16B16Unorm;
|
||||
case VkFormat.R16G16B16A16SNorm:
|
||||
return VkFormat.R16G16B16SNorm;
|
||||
case VkFormat.R16G16B16A16Uint:
|
||||
return VkFormat.R16G16B16Uint;
|
||||
case VkFormat.R16G16B16A16Sint:
|
||||
return VkFormat.R16G16B16Sint;
|
||||
case VkFormat.R16G16B16A16Uscaled:
|
||||
return VkFormat.R16G16B16Uscaled;
|
||||
case VkFormat.R16G16B16A16Sscaled:
|
||||
return VkFormat.R16G16B16Sscaled;
|
||||
|
||||
case VkFormat.R32G32Sfloat:
|
||||
return VkFormat.R32Sfloat;
|
||||
case VkFormat.R32G32Uint:
|
||||
return VkFormat.R32Uint;
|
||||
case VkFormat.R32G32Sint:
|
||||
return VkFormat.R32Sint;
|
||||
|
||||
case VkFormat.R32G32B32Sfloat:
|
||||
return VkFormat.R32G32Sfloat;
|
||||
case VkFormat.R32G32B32Uint:
|
||||
return VkFormat.R32G32Uint;
|
||||
case VkFormat.R32G32B32Sint:
|
||||
return VkFormat.R32G32Sint;
|
||||
|
||||
case VkFormat.R32G32B32A32Sfloat:
|
||||
return VkFormat.R32G32B32Sfloat;
|
||||
case VkFormat.R32G32B32A32Uint:
|
||||
return VkFormat.R32G32B32Uint;
|
||||
case VkFormat.R32G32B32A32Sint:
|
||||
return VkFormat.R32G32B32Sint;
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
public readonly bool SupportsSubgroupSizeControl;
|
||||
public readonly bool SupportsShaderInt8;
|
||||
public readonly bool SupportsShaderStencilExport;
|
||||
public readonly bool SupportsShaderStorageImageMultisample;
|
||||
public readonly bool SupportsConditionalRendering;
|
||||
public readonly bool SupportsExtendedDynamicState;
|
||||
public readonly bool SupportsMultiView;
|
||||
@ -63,6 +64,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
bool supportsSubgroupSizeControl,
|
||||
bool supportsShaderInt8,
|
||||
bool supportsShaderStencilExport,
|
||||
bool supportsShaderStorageImageMultisample,
|
||||
bool supportsConditionalRendering,
|
||||
bool supportsExtendedDynamicState,
|
||||
bool supportsMultiView,
|
||||
@ -97,6 +99,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
SupportsSubgroupSizeControl = supportsSubgroupSizeControl;
|
||||
SupportsShaderInt8 = supportsShaderInt8;
|
||||
SupportsShaderStencilExport = supportsShaderStencilExport;
|
||||
SupportsShaderStorageImageMultisample = supportsShaderStorageImageMultisample;
|
||||
SupportsConditionalRendering = supportsConditionalRendering;
|
||||
SupportsExtendedDynamicState = supportsExtendedDynamicState;
|
||||
SupportsMultiView = supportsMultiView;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Silk.NET.Vulkan;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
@ -308,6 +309,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
public PipelineLayout PipelineLayout;
|
||||
public SpecData SpecializationData;
|
||||
|
||||
private Array32<VertexInputAttributeDescription> _vertexAttributeDescriptions2;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
Stages = new NativeArray<PipelineShaderStageCreateInfo>(Constants.MaxShaderStages);
|
||||
@ -400,7 +403,15 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
Pipeline pipelineHandle = default;
|
||||
|
||||
bool isMoltenVk = gd.IsMoltenVk;
|
||||
|
||||
if (isMoltenVk)
|
||||
{
|
||||
UpdateVertexAttributeDescriptions();
|
||||
}
|
||||
|
||||
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
|
||||
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0])
|
||||
fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0])
|
||||
fixed (Viewport* pViewports = &Internal.Viewports[0])
|
||||
fixed (Rect2D* pScissors = &Internal.Scissors[0])
|
||||
@ -410,7 +421,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
SType = StructureType.PipelineVertexInputStateCreateInfo,
|
||||
VertexAttributeDescriptionCount = VertexAttributeDescriptionsCount,
|
||||
PVertexAttributeDescriptions = pVertexAttributeDescriptions,
|
||||
PVertexAttributeDescriptions = isMoltenVk ? pVertexAttributeDescriptions2 : pVertexAttributeDescriptions,
|
||||
VertexBindingDescriptionCount = VertexBindingDescriptionsCount,
|
||||
PVertexBindingDescriptions = pVertexBindingDescriptions
|
||||
};
|
||||
@ -612,6 +623,40 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVertexAttributeDescriptions()
|
||||
{
|
||||
// Vertex attributes exceeding the stride are invalid.
|
||||
// In metal, they cause glitches with the vertex shader fetching incorrect values.
|
||||
// To work around this, we reduce the format to something that doesn't exceed the stride if possible.
|
||||
// The assumption is that the exceeding components are not actually accessed on the shader.
|
||||
|
||||
for (int index = 0; index < VertexAttributeDescriptionsCount; index++)
|
||||
{
|
||||
var attribute = Internal.VertexAttributeDescriptions[index];
|
||||
ref var vb = ref Internal.VertexBindingDescriptions[(int)attribute.Binding];
|
||||
|
||||
Format format = attribute.Format;
|
||||
|
||||
while (vb.Stride != 0 && attribute.Offset + FormatTable.GetAttributeFormatSize(format) > vb.Stride)
|
||||
{
|
||||
Format newFormat = FormatTable.DropLastComponent(format);
|
||||
|
||||
if (newFormat == format)
|
||||
{
|
||||
// That case means we failed to find a format that fits within the stride,
|
||||
// so just restore the original format and give up.
|
||||
format = attribute.Format;
|
||||
break;
|
||||
}
|
||||
|
||||
format = newFormat;
|
||||
}
|
||||
|
||||
attribute.Format = format;
|
||||
_vertexAttributeDescriptions2[index] = attribute;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Stages.Dispose();
|
||||
|
@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples);
|
||||
|
||||
var usage = GetImageUsageFromFormat(info.Format);
|
||||
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample);
|
||||
|
||||
var flags = ImageCreateFlags.CreateMutableFormatBit;
|
||||
|
||||
@ -293,7 +293,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
public static ImageUsageFlags GetImageUsageFromFormat(GAL.Format format)
|
||||
public static ImageUsageFlags GetImageUsage(GAL.Format format, Target target, bool supportsMsStorage)
|
||||
{
|
||||
var usage = DefaultUsageFlags;
|
||||
|
||||
@ -306,7 +306,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
usage |= ImageUsageFlags.ColorAttachmentBit;
|
||||
}
|
||||
|
||||
if (format.IsImageCompatible())
|
||||
if (format.IsImageCompatible() && (supportsMsStorage || !target.IsMultisample()))
|
||||
{
|
||||
usage |= ImageUsageFlags.StorageBit;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
gd.Textures.Add(this);
|
||||
|
||||
var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format);
|
||||
var usage = TextureStorage.GetImageUsageFromFormat(info.Format);
|
||||
var usage = TextureStorage.GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample);
|
||||
var levels = (uint)info.Levels;
|
||||
var layers = (uint)info.GetLayers();
|
||||
|
||||
|
@ -295,6 +295,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
supportsSubgroupSizeControl,
|
||||
featuresShaderInt8.ShaderInt8,
|
||||
_physicalDevice.IsDeviceExtensionPresent("VK_EXT_shader_stencil_export"),
|
||||
features2.Features.ShaderStorageImageMultisample,
|
||||
_physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName),
|
||||
_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName),
|
||||
features2.Features.MultiViewport,
|
||||
|
Reference in New Issue
Block a user