Merge branch 'master' of https://github.com/Ryujinx/Ryujinx into turbo
This commit is contained in:
commit
20cd474994
27 changed files with 457 additions and 247 deletions
|
@ -1,6 +1,8 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.GAL
|
namespace Ryujinx.Graphics.GAL
|
||||||
{
|
{
|
||||||
public interface IImageArray
|
public interface IImageArray : IDisposable
|
||||||
{
|
{
|
||||||
void SetFormats(int index, Format[] imageFormats);
|
void SetFormats(int index, Format[] imageFormats);
|
||||||
void SetImages(int index, ITexture[] images);
|
void SetImages(int index, ITexture[] images);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.GAL
|
namespace Ryujinx.Graphics.GAL
|
||||||
{
|
{
|
||||||
public interface ITextureArray
|
public interface ITextureArray : IDisposable
|
||||||
{
|
{
|
||||||
void SetSamplers(int index, ISampler[] samplers);
|
void SetSamplers(int index, ISampler[] samplers);
|
||||||
void SetTextures(int index, ITexture[] textures);
|
void SetTextures(int index, ITexture[] textures);
|
||||||
|
|
|
@ -66,6 +66,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||||
Register<CounterEventDisposeCommand>(CommandType.CounterEventDispose);
|
Register<CounterEventDisposeCommand>(CommandType.CounterEventDispose);
|
||||||
Register<CounterEventFlushCommand>(CommandType.CounterEventFlush);
|
Register<CounterEventFlushCommand>(CommandType.CounterEventFlush);
|
||||||
|
|
||||||
|
Register<ImageArrayDisposeCommand>(CommandType.ImageArrayDispose);
|
||||||
Register<ImageArraySetFormatsCommand>(CommandType.ImageArraySetFormats);
|
Register<ImageArraySetFormatsCommand>(CommandType.ImageArraySetFormats);
|
||||||
Register<ImageArraySetImagesCommand>(CommandType.ImageArraySetImages);
|
Register<ImageArraySetImagesCommand>(CommandType.ImageArraySetImages);
|
||||||
|
|
||||||
|
@ -88,6 +89,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||||
Register<TextureSetDataSliceRegionCommand>(CommandType.TextureSetDataSliceRegion);
|
Register<TextureSetDataSliceRegionCommand>(CommandType.TextureSetDataSliceRegion);
|
||||||
Register<TextureSetStorageCommand>(CommandType.TextureSetStorage);
|
Register<TextureSetStorageCommand>(CommandType.TextureSetStorage);
|
||||||
|
|
||||||
|
Register<TextureArrayDisposeCommand>(CommandType.TextureArrayDispose);
|
||||||
Register<TextureArraySetSamplersCommand>(CommandType.TextureArraySetSamplers);
|
Register<TextureArraySetSamplersCommand>(CommandType.TextureArraySetSamplers);
|
||||||
Register<TextureArraySetTexturesCommand>(CommandType.TextureArraySetTextures);
|
Register<TextureArraySetTexturesCommand>(CommandType.TextureArraySetTextures);
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||||
CounterEventDispose,
|
CounterEventDispose,
|
||||||
CounterEventFlush,
|
CounterEventFlush,
|
||||||
|
|
||||||
|
ImageArrayDispose,
|
||||||
ImageArraySetFormats,
|
ImageArraySetFormats,
|
||||||
ImageArraySetImages,
|
ImageArraySetImages,
|
||||||
|
|
||||||
|
@ -48,6 +49,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
||||||
TextureSetDataSliceRegion,
|
TextureSetDataSliceRegion,
|
||||||
TextureSetStorage,
|
TextureSetStorage,
|
||||||
|
|
||||||
|
TextureArrayDispose,
|
||||||
TextureArraySetSamplers,
|
TextureArraySetSamplers,
|
||||||
TextureArraySetTextures,
|
TextureArraySetTextures,
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||||
|
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.ImageArray
|
||||||
|
{
|
||||||
|
struct ImageArrayDisposeCommand : IGALCommand, IGALCommand<ImageArrayDisposeCommand>
|
||||||
|
{
|
||||||
|
public readonly CommandType CommandType => CommandType.ImageArrayDispose;
|
||||||
|
private TableRef<ThreadedImageArray> _imageArray;
|
||||||
|
|
||||||
|
public void Set(TableRef<ThreadedImageArray> imageArray)
|
||||||
|
{
|
||||||
|
_imageArray = imageArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Run(ref ImageArrayDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
|
{
|
||||||
|
command._imageArray.Get(threaded).Base.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||||
|
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.TextureArray
|
||||||
|
{
|
||||||
|
struct TextureArrayDisposeCommand : IGALCommand, IGALCommand<TextureArrayDisposeCommand>
|
||||||
|
{
|
||||||
|
public readonly CommandType CommandType => CommandType.TextureArrayDispose;
|
||||||
|
private TableRef<ThreadedTextureArray> _textureArray;
|
||||||
|
|
||||||
|
public void Set(TableRef<ThreadedTextureArray> textureArray)
|
||||||
|
{
|
||||||
|
_textureArray = textureArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Run(ref TextureArrayDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
|
{
|
||||||
|
command._textureArray.Get(threaded).Base.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
||||||
return new TableRef<T>(_renderer, reference);
|
return new TableRef<T>(_renderer, reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_renderer.New<ImageArrayDisposeCommand>().Set(Ref(this));
|
||||||
|
_renderer.QueueCommand();
|
||||||
|
}
|
||||||
|
|
||||||
public void SetFormats(int index, Format[] imageFormats)
|
public void SetFormats(int index, Format[] imageFormats)
|
||||||
{
|
{
|
||||||
_renderer.New<ImageArraySetFormatsCommand>().Set(Ref(this), index, Ref(imageFormats));
|
_renderer.New<ImageArraySetFormatsCommand>().Set(Ref(this), index, Ref(imageFormats));
|
||||||
|
|
|
@ -22,6 +22,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
|
||||||
return new TableRef<T>(_renderer, reference);
|
return new TableRef<T>(_renderer, reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_renderer.New<TextureArrayDisposeCommand>().Set(Ref(this));
|
||||||
|
_renderer.QueueCommand();
|
||||||
|
}
|
||||||
|
|
||||||
public void SetSamplers(int index, ISampler[] samplers)
|
public void SetSamplers(int index, ISampler[] samplers)
|
||||||
{
|
{
|
||||||
_renderer.New<TextureArraySetSamplersCommand>().Set(Ref(this), index, Ref(samplers.ToArray()));
|
_renderer.New<TextureArraySetSamplersCommand>().Set(Ref(this), index, Ref(samplers.ToArray()));
|
||||||
|
|
|
@ -1113,6 +1113,15 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
nextNode = nextNode.Next;
|
nextNode = nextNode.Next;
|
||||||
_cacheFromBuffer.Remove(toRemove.Value.Key);
|
_cacheFromBuffer.Remove(toRemove.Value.Key);
|
||||||
_lruCache.Remove(toRemove);
|
_lruCache.Remove(toRemove);
|
||||||
|
|
||||||
|
if (toRemove.Value.Key.IsImage)
|
||||||
|
{
|
||||||
|
toRemove.Value.ImageArray.Dispose();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toRemove.Value.TextureArray.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1124,11 +1133,20 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
List<CacheEntryFromPoolKey> keysToRemove = null;
|
List<CacheEntryFromPoolKey> keysToRemove = null;
|
||||||
|
|
||||||
foreach (CacheEntryFromPoolKey key in _cacheFromPool.Keys)
|
foreach ((CacheEntryFromPoolKey key, CacheEntry entry) in _cacheFromPool)
|
||||||
{
|
{
|
||||||
if (key.MatchesPool(pool))
|
if (key.MatchesPool(pool))
|
||||||
{
|
{
|
||||||
(keysToRemove ??= new()).Add(key);
|
(keysToRemove ??= new()).Add(key);
|
||||||
|
|
||||||
|
if (key.IsImage)
|
||||||
|
{
|
||||||
|
entry.ImageArray.Dispose();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry.TextureArray.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,5 +63,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,5 +48,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,11 +98,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
Logger = parameters.Logger;
|
Logger = parameters.Logger;
|
||||||
TargetApi = parameters.TargetApi;
|
TargetApi = parameters.TargetApi;
|
||||||
|
|
||||||
AddCapability(Capability.Shader);
|
|
||||||
AddCapability(Capability.Float64);
|
|
||||||
|
|
||||||
SetMemoryModel(AddressingModel.Logical, MemoryModel.GLSL450);
|
|
||||||
|
|
||||||
Delegates = new SpirvDelegates(this);
|
Delegates = new SpirvDelegates(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
|
|
||||||
CodeGenContext context = new(info, parameters, instPool, integerPool);
|
CodeGenContext context = new(info, parameters, instPool, integerPool);
|
||||||
|
|
||||||
|
context.AddCapability(Capability.Shader);
|
||||||
|
|
||||||
|
context.SetMemoryModel(AddressingModel.Logical, MemoryModel.GLSL450);
|
||||||
|
|
||||||
context.AddCapability(Capability.GroupNonUniformBallot);
|
context.AddCapability(Capability.GroupNonUniformBallot);
|
||||||
context.AddCapability(Capability.GroupNonUniformShuffle);
|
context.AddCapability(Capability.GroupNonUniformShuffle);
|
||||||
context.AddCapability(Capability.GroupNonUniformVote);
|
context.AddCapability(Capability.GroupNonUniformVote);
|
||||||
|
@ -51,6 +55,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
context.AddCapability(Capability.ImageQuery);
|
context.AddCapability(Capability.ImageQuery);
|
||||||
context.AddCapability(Capability.SampledBuffer);
|
context.AddCapability(Capability.SampledBuffer);
|
||||||
|
|
||||||
|
if (parameters.HostCapabilities.SupportsShaderFloat64)
|
||||||
|
{
|
||||||
|
context.AddCapability(Capability.Float64);
|
||||||
|
}
|
||||||
|
|
||||||
if (parameters.Definitions.TransformFeedbackEnabled && parameters.Definitions.LastInVertexPipeline)
|
if (parameters.Definitions.TransformFeedbackEnabled && parameters.Definitions.LastInVertexPipeline)
|
||||||
{
|
{
|
||||||
context.AddCapability(Capability.TransformFeedback);
|
context.AddCapability(Capability.TransformFeedback);
|
||||||
|
@ -58,7 +67,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||||
|
|
||||||
if (parameters.Definitions.Stage == ShaderStage.Fragment)
|
if (parameters.Definitions.Stage == ShaderStage.Fragment)
|
||||||
{
|
{
|
||||||
if (context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Input, IoVariable.Layer)))
|
if (context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Input, IoVariable.Layer)) ||
|
||||||
|
context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Input, IoVariable.PrimitiveId)))
|
||||||
{
|
{
|
||||||
context.AddCapability(Capability.Geometry);
|
context.AddCapability(Capability.Geometry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
public readonly bool SupportsGeometryShaderPassthrough;
|
public readonly bool SupportsGeometryShaderPassthrough;
|
||||||
public readonly bool SupportsShaderBallot;
|
public readonly bool SupportsShaderBallot;
|
||||||
public readonly bool SupportsShaderBarrierDivergence;
|
public readonly bool SupportsShaderBarrierDivergence;
|
||||||
|
public readonly bool SupportsShaderFloat64;
|
||||||
public readonly bool SupportsTextureShadowLod;
|
public readonly bool SupportsTextureShadowLod;
|
||||||
public readonly bool SupportsViewportMask;
|
public readonly bool SupportsViewportMask;
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
bool supportsGeometryShaderPassthrough,
|
bool supportsGeometryShaderPassthrough,
|
||||||
bool supportsShaderBallot,
|
bool supportsShaderBallot,
|
||||||
bool supportsShaderBarrierDivergence,
|
bool supportsShaderBarrierDivergence,
|
||||||
|
bool supportsShaderFloat64,
|
||||||
bool supportsTextureShadowLod,
|
bool supportsTextureShadowLod,
|
||||||
bool supportsViewportMask)
|
bool supportsViewportMask)
|
||||||
{
|
{
|
||||||
|
@ -27,6 +29,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
|
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
|
||||||
SupportsShaderBallot = supportsShaderBallot;
|
SupportsShaderBallot = supportsShaderBallot;
|
||||||
SupportsShaderBarrierDivergence = supportsShaderBarrierDivergence;
|
SupportsShaderBarrierDivergence = supportsShaderBarrierDivergence;
|
||||||
|
SupportsShaderFloat64 = supportsShaderFloat64;
|
||||||
SupportsTextureShadowLod = supportsTextureShadowLod;
|
SupportsTextureShadowLod = supportsTextureShadowLod;
|
||||||
SupportsViewportMask = supportsViewportMask;
|
SupportsViewportMask = supportsViewportMask;
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,6 +363,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
GpuAccessor.QueryHostSupportsGeometryShaderPassthrough(),
|
GpuAccessor.QueryHostSupportsGeometryShaderPassthrough(),
|
||||||
GpuAccessor.QueryHostSupportsShaderBallot(),
|
GpuAccessor.QueryHostSupportsShaderBallot(),
|
||||||
GpuAccessor.QueryHostSupportsShaderBarrierDivergence(),
|
GpuAccessor.QueryHostSupportsShaderBarrierDivergence(),
|
||||||
|
GpuAccessor.QueryHostSupportsShaderFloat64(),
|
||||||
GpuAccessor.QueryHostSupportsTextureShadowLod(),
|
GpuAccessor.QueryHostSupportsTextureShadowLod(),
|
||||||
GpuAccessor.QueryHostSupportsViewportMask());
|
GpuAccessor.QueryHostSupportsViewportMask());
|
||||||
|
|
||||||
|
|
|
@ -291,8 +291,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PipelineStageFlags stageFlags = _textureArrayRefs[segment.Binding].Stage.ConvertToPipelineStageFlags();
|
ref var arrayRef = ref _textureArrayRefs[segment.Binding];
|
||||||
_textureArrayRefs[segment.Binding].Array?.QueueWriteToReadBarriers(cbs, stageFlags);
|
PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags();
|
||||||
|
arrayRef.Array?.QueueWriteToReadBarriers(cbs, stageFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,8 +312,40 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PipelineStageFlags stageFlags = _imageArrayRefs[segment.Binding].Stage.ConvertToPipelineStageFlags();
|
ref var arrayRef = ref _imageArrayRefs[segment.Binding];
|
||||||
_imageArrayRefs[segment.Binding].Array?.QueueWriteToReadBarriers(cbs, stageFlags);
|
PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags();
|
||||||
|
arrayRef.Array?.QueueWriteToReadBarriers(cbs, stageFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int setIndex = PipelineBase.DescriptorSetLayouts; setIndex < _program.BindingSegments.Length; setIndex++)
|
||||||
|
{
|
||||||
|
var bindingSegments = _program.BindingSegments[setIndex];
|
||||||
|
|
||||||
|
if (bindingSegments.Length == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceBindingSegment segment = bindingSegments[0];
|
||||||
|
|
||||||
|
if (segment.IsArray)
|
||||||
|
{
|
||||||
|
if (segment.Type == ResourceType.Texture ||
|
||||||
|
segment.Type == ResourceType.Sampler ||
|
||||||
|
segment.Type == ResourceType.TextureAndSampler ||
|
||||||
|
segment.Type == ResourceType.BufferTexture)
|
||||||
|
{
|
||||||
|
ref var arrayRef = ref _textureArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts];
|
||||||
|
PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags();
|
||||||
|
arrayRef.Array?.QueueWriteToReadBarriers(cbs, stageFlags);
|
||||||
|
}
|
||||||
|
else if (segment.Type == ResourceType.Image || segment.Type == ResourceType.BufferImage)
|
||||||
|
{
|
||||||
|
ref var arrayRef = ref _imageArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts];
|
||||||
|
PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags();
|
||||||
|
arrayRef.Array?.QueueWriteToReadBarriers(cbs, stageFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,10 @@ using Ryujinx.Graphics.GAL;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
class ImageArray : IImageArray
|
class ImageArray : ResourceArray, IImageArray
|
||||||
{
|
{
|
||||||
private readonly VulkanRenderer _gd;
|
private readonly VulkanRenderer _gd;
|
||||||
|
|
||||||
|
@ -25,19 +24,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
private HashSet<TextureStorage> _storages;
|
private HashSet<TextureStorage> _storages;
|
||||||
|
|
||||||
private DescriptorSet[] _cachedDescriptorSets;
|
|
||||||
|
|
||||||
private int _cachedCommandBufferIndex;
|
private int _cachedCommandBufferIndex;
|
||||||
private int _cachedSubmissionCount;
|
private int _cachedSubmissionCount;
|
||||||
|
|
||||||
private ShaderCollection _cachedDscProgram;
|
|
||||||
private int _cachedDscSetIndex;
|
|
||||||
private int _cachedDscIndex;
|
|
||||||
|
|
||||||
private readonly bool _isBuffer;
|
private readonly bool _isBuffer;
|
||||||
|
|
||||||
private int _bindCount;
|
|
||||||
|
|
||||||
public ImageArray(VulkanRenderer gd, int size, bool isBuffer)
|
public ImageArray(VulkanRenderer gd, int size, bool isBuffer)
|
||||||
{
|
{
|
||||||
_gd = gd;
|
_gd = gd;
|
||||||
|
@ -104,12 +95,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
_cachedCommandBufferIndex = -1;
|
_cachedCommandBufferIndex = -1;
|
||||||
_storages = null;
|
_storages = null;
|
||||||
_cachedDescriptorSets = null;
|
SetDirty(_gd);
|
||||||
|
|
||||||
if (_bindCount != 0)
|
|
||||||
{
|
|
||||||
_gd.PipelineInternal.ForceImageDirty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
|
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
|
||||||
|
@ -195,7 +181,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
int setIndex,
|
int setIndex,
|
||||||
TextureView dummyTexture)
|
TextureView dummyTexture)
|
||||||
{
|
{
|
||||||
if (_cachedDescriptorSets != null)
|
if (TryGetCachedDescriptorSets(cbs, program, setIndex, out DescriptorSet[] sets))
|
||||||
{
|
{
|
||||||
// We still need to ensure the current command buffer holds a reference to all used textures.
|
// We still need to ensure the current command buffer holds a reference to all used textures.
|
||||||
|
|
||||||
|
@ -208,12 +194,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
GetBufferViews(cbs);
|
GetBufferViews(cbs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _cachedDescriptorSets;
|
return sets;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cachedDscProgram?.ReleaseManualDescriptorSetCollection(_cachedDscSetIndex, _cachedDscIndex);
|
|
||||||
var dsc = program.GetNewManualDescriptorSetCollection(cbs.CommandBufferIndex, setIndex, out _cachedDscIndex).Get(cbs);
|
|
||||||
|
|
||||||
DescriptorSetTemplate template = program.Templates[setIndex];
|
DescriptorSetTemplate template = program.Templates[setIndex];
|
||||||
|
|
||||||
DescriptorSetTemplateWriter tu = templateUpdater.Begin(template);
|
DescriptorSetTemplateWriter tu = templateUpdater.Begin(template);
|
||||||
|
@ -227,24 +210,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
tu.Push(GetBufferViews(cbs));
|
tu.Push(GetBufferViews(cbs));
|
||||||
}
|
}
|
||||||
|
|
||||||
var sets = dsc.GetSets();
|
|
||||||
templateUpdater.Commit(_gd, device, sets[0]);
|
templateUpdater.Commit(_gd, device, sets[0]);
|
||||||
_cachedDescriptorSets = sets;
|
|
||||||
_cachedDscProgram = program;
|
|
||||||
_cachedDscSetIndex = setIndex;
|
|
||||||
|
|
||||||
return sets;
|
return sets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void IncrementBindCount()
|
|
||||||
{
|
|
||||||
_bindCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DecrementBindCount()
|
|
||||||
{
|
|
||||||
int newBindCount = --_bindCount;
|
|
||||||
Debug.Assert(newBindCount >= 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,9 +180,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
pipeline.LogicOpEnable = state.LogicOpEnable;
|
pipeline.LogicOpEnable = state.LogicOpEnable;
|
||||||
pipeline.LogicOp = state.LogicOp.Convert();
|
pipeline.LogicOp = state.LogicOp.Convert();
|
||||||
|
|
||||||
pipeline.MinDepthBounds = 0f; // Not implemented.
|
|
||||||
pipeline.MaxDepthBounds = 0f; // Not implemented.
|
|
||||||
|
|
||||||
pipeline.PatchControlPoints = state.PatchControlPoints;
|
pipeline.PatchControlPoints = state.PatchControlPoints;
|
||||||
pipeline.PolygonMode = PolygonMode.Fill; // Not implemented.
|
pipeline.PolygonMode = PolygonMode.Fill; // Not implemented.
|
||||||
pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable;
|
pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable;
|
||||||
|
@ -208,17 +205,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert();
|
pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert();
|
||||||
pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert();
|
pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert();
|
||||||
pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert();
|
pipeline.StencilFrontCompareOp = state.StencilTest.FrontFunc.Convert();
|
||||||
pipeline.StencilFrontCompareMask = 0;
|
|
||||||
pipeline.StencilFrontWriteMask = 0;
|
|
||||||
pipeline.StencilFrontReference = 0;
|
|
||||||
|
|
||||||
pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert();
|
pipeline.StencilBackFailOp = state.StencilTest.BackSFail.Convert();
|
||||||
pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert();
|
pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert();
|
||||||
pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert();
|
pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert();
|
||||||
pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert();
|
pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert();
|
||||||
pipeline.StencilBackCompareMask = 0;
|
|
||||||
pipeline.StencilBackWriteMask = 0;
|
|
||||||
pipeline.StencilBackReference = 0;
|
|
||||||
|
|
||||||
pipeline.StencilTestEnable = state.StencilTest.TestEnable;
|
pipeline.StencilTestEnable = state.StencilTest.TestEnable;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
|
@ -15,6 +16,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
private readonly Device _device;
|
private readonly Device _device;
|
||||||
|
|
||||||
public DescriptorSetLayout[] DescriptorSetLayouts { get; }
|
public DescriptorSetLayout[] DescriptorSetLayouts { get; }
|
||||||
|
public bool[] DescriptorSetLayoutsUpdateAfterBind { get; }
|
||||||
public PipelineLayout PipelineLayout { get; }
|
public PipelineLayout PipelineLayout { get; }
|
||||||
|
|
||||||
private readonly int[] _consumedDescriptorsPerSet;
|
private readonly int[] _consumedDescriptorsPerSet;
|
||||||
|
@ -31,20 +33,37 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
private struct ManualDescriptorSetEntry
|
private struct ManualDescriptorSetEntry
|
||||||
{
|
{
|
||||||
public Auto<DescriptorSetCollection> DescriptorSet;
|
public Auto<DescriptorSetCollection> DescriptorSet;
|
||||||
public int CbIndex;
|
public uint CbRefMask;
|
||||||
public int CbSubmissionCount;
|
|
||||||
public bool InUse;
|
public bool InUse;
|
||||||
|
|
||||||
public ManualDescriptorSetEntry(Auto<DescriptorSetCollection> descriptorSet, int cbIndex, int cbSubmissionCount, bool inUse)
|
public ManualDescriptorSetEntry(Auto<DescriptorSetCollection> descriptorSet, int cbIndex)
|
||||||
{
|
{
|
||||||
DescriptorSet = descriptorSet;
|
DescriptorSet = descriptorSet;
|
||||||
CbIndex = cbIndex;
|
CbRefMask = 1u << cbIndex;
|
||||||
CbSubmissionCount = cbSubmissionCount;
|
InUse = true;
|
||||||
InUse = inUse;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly struct PendingManualDsConsumption
|
||||||
|
{
|
||||||
|
public FenceHolder Fence { get; }
|
||||||
|
public int CommandBufferIndex { get; }
|
||||||
|
public int SetIndex { get; }
|
||||||
|
public int CacheIndex { get; }
|
||||||
|
|
||||||
|
public PendingManualDsConsumption(FenceHolder fence, int commandBufferIndex, int setIndex, int cacheIndex)
|
||||||
|
{
|
||||||
|
Fence = fence;
|
||||||
|
CommandBufferIndex = commandBufferIndex;
|
||||||
|
SetIndex = setIndex;
|
||||||
|
CacheIndex = cacheIndex;
|
||||||
|
fence.Get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly List<ManualDescriptorSetEntry>[] _manualDsCache;
|
private readonly List<ManualDescriptorSetEntry>[] _manualDsCache;
|
||||||
|
private readonly Queue<PendingManualDsConsumption> _pendingManualDsConsumptions;
|
||||||
|
private readonly Queue<int>[] _freeManualDsCacheEntries;
|
||||||
|
|
||||||
private readonly Dictionary<long, DescriptorSetTemplate> _pdTemplates;
|
private readonly Dictionary<long, DescriptorSetTemplate> _pdTemplates;
|
||||||
private readonly ResourceDescriptorCollection _pdDescriptors;
|
private readonly ResourceDescriptorCollection _pdDescriptors;
|
||||||
|
@ -70,6 +89,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
_dsCacheCursor = new int[setsCount];
|
_dsCacheCursor = new int[setsCount];
|
||||||
_manualDsCache = new List<ManualDescriptorSetEntry>[setsCount];
|
_manualDsCache = new List<ManualDescriptorSetEntry>[setsCount];
|
||||||
|
_pendingManualDsConsumptions = new Queue<PendingManualDsConsumption>();
|
||||||
|
_freeManualDsCacheEntries = new Queue<int>[setsCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
public PipelineLayoutCacheEntry(
|
public PipelineLayoutCacheEntry(
|
||||||
|
@ -78,7 +99,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
ReadOnlyCollection<ResourceDescriptorCollection> setDescriptors,
|
ReadOnlyCollection<ResourceDescriptorCollection> setDescriptors,
|
||||||
bool usePushDescriptors) : this(gd, device, setDescriptors.Count)
|
bool usePushDescriptors) : this(gd, device, setDescriptors.Count)
|
||||||
{
|
{
|
||||||
(DescriptorSetLayouts, PipelineLayout) = PipelineLayoutFactory.Create(gd, device, setDescriptors, usePushDescriptors);
|
ResourceLayouts layouts = PipelineLayoutFactory.Create(gd, device, setDescriptors, usePushDescriptors);
|
||||||
|
|
||||||
|
DescriptorSetLayouts = layouts.DescriptorSetLayouts;
|
||||||
|
DescriptorSetLayoutsUpdateAfterBind = layouts.DescriptorSetLayoutsUpdateAfterBind;
|
||||||
|
PipelineLayout = layouts.PipelineLayout;
|
||||||
|
|
||||||
_consumedDescriptorsPerSet = new int[setDescriptors.Count];
|
_consumedDescriptorsPerSet = new int[setDescriptors.Count];
|
||||||
_poolSizes = new DescriptorPoolSize[setDescriptors.Count][];
|
_poolSizes = new DescriptorPoolSize[setDescriptors.Count][];
|
||||||
|
@ -133,7 +158,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
_poolSizes[setIndex],
|
_poolSizes[setIndex],
|
||||||
setIndex,
|
setIndex,
|
||||||
_consumedDescriptorsPerSet[setIndex],
|
_consumedDescriptorsPerSet[setIndex],
|
||||||
false);
|
DescriptorSetLayoutsUpdateAfterBind[setIndex]);
|
||||||
|
|
||||||
list.Add(dsc);
|
list.Add(dsc);
|
||||||
isNew = true;
|
isNew = true;
|
||||||
|
@ -144,49 +169,99 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
return list[index];
|
return list[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public Auto<DescriptorSetCollection> GetNewManualDescriptorSetCollection(int commandBufferIndex, int setIndex, out int cacheIndex)
|
public Auto<DescriptorSetCollection> GetNewManualDescriptorSetCollection(CommandBufferScoped cbs, int setIndex, out int cacheIndex)
|
||||||
{
|
{
|
||||||
int submissionCount = _gd.CommandBufferPool.GetSubmissionCount(commandBufferIndex);
|
FreeCompletedManualDescriptorSets();
|
||||||
|
|
||||||
var list = _manualDsCache[setIndex] ??= new();
|
var list = _manualDsCache[setIndex] ??= new();
|
||||||
var span = CollectionsMarshal.AsSpan(list);
|
var span = CollectionsMarshal.AsSpan(list);
|
||||||
|
|
||||||
for (int index = 0; index < span.Length; index++)
|
Queue<int> freeQueue = _freeManualDsCacheEntries[setIndex];
|
||||||
|
|
||||||
|
// Do we have at least one freed descriptor set? If so, just use that.
|
||||||
|
if (freeQueue != null && freeQueue.TryDequeue(out int freeIndex))
|
||||||
{
|
{
|
||||||
ref ManualDescriptorSetEntry entry = ref span[index];
|
ref ManualDescriptorSetEntry entry = ref span[freeIndex];
|
||||||
|
|
||||||
if (!entry.InUse && (entry.CbIndex != commandBufferIndex || entry.CbSubmissionCount != submissionCount))
|
Debug.Assert(!entry.InUse && entry.CbRefMask == 0);
|
||||||
{
|
|
||||||
entry.InUse = true;
|
|
||||||
entry.CbIndex = commandBufferIndex;
|
|
||||||
entry.CbSubmissionCount = submissionCount;
|
|
||||||
|
|
||||||
cacheIndex = index;
|
entry.InUse = true;
|
||||||
|
entry.CbRefMask = 1u << cbs.CommandBufferIndex;
|
||||||
|
cacheIndex = freeIndex;
|
||||||
|
|
||||||
return entry.DescriptorSet;
|
_pendingManualDsConsumptions.Enqueue(new PendingManualDsConsumption(cbs.GetFence(), cbs.CommandBufferIndex, setIndex, freeIndex));
|
||||||
}
|
|
||||||
|
return entry.DescriptorSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise create a new descriptor set, and add to our pending queue for command buffer consumption tracking.
|
||||||
var dsc = _descriptorSetManager.AllocateDescriptorSet(
|
var dsc = _descriptorSetManager.AllocateDescriptorSet(
|
||||||
_gd.Api,
|
_gd.Api,
|
||||||
DescriptorSetLayouts[setIndex],
|
DescriptorSetLayouts[setIndex],
|
||||||
_poolSizes[setIndex],
|
_poolSizes[setIndex],
|
||||||
setIndex,
|
setIndex,
|
||||||
_consumedDescriptorsPerSet[setIndex],
|
_consumedDescriptorsPerSet[setIndex],
|
||||||
false);
|
DescriptorSetLayoutsUpdateAfterBind[setIndex]);
|
||||||
|
|
||||||
cacheIndex = list.Count;
|
cacheIndex = list.Count;
|
||||||
list.Add(new ManualDescriptorSetEntry(dsc, commandBufferIndex, submissionCount, inUse: true));
|
list.Add(new ManualDescriptorSetEntry(dsc, cbs.CommandBufferIndex));
|
||||||
|
_pendingManualDsConsumptions.Enqueue(new PendingManualDsConsumption(cbs.GetFence(), cbs.CommandBufferIndex, setIndex, cacheIndex));
|
||||||
|
|
||||||
return dsc;
|
return dsc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateManualDescriptorSetCollectionOwnership(CommandBufferScoped cbs, int setIndex, int cacheIndex)
|
||||||
|
{
|
||||||
|
FreeCompletedManualDescriptorSets();
|
||||||
|
|
||||||
|
var list = _manualDsCache[setIndex];
|
||||||
|
var span = CollectionsMarshal.AsSpan(list);
|
||||||
|
ref var entry = ref span[cacheIndex];
|
||||||
|
|
||||||
|
uint cbMask = 1u << cbs.CommandBufferIndex;
|
||||||
|
|
||||||
|
if ((entry.CbRefMask & cbMask) == 0)
|
||||||
|
{
|
||||||
|
entry.CbRefMask |= cbMask;
|
||||||
|
|
||||||
|
_pendingManualDsConsumptions.Enqueue(new PendingManualDsConsumption(cbs.GetFence(), cbs.CommandBufferIndex, setIndex, cacheIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FreeCompletedManualDescriptorSets()
|
||||||
|
{
|
||||||
|
FenceHolder signalledFence = null;
|
||||||
|
while (_pendingManualDsConsumptions.TryPeek(out var pds) && (pds.Fence == signalledFence || pds.Fence.IsSignaled()))
|
||||||
|
{
|
||||||
|
signalledFence = pds.Fence; // Already checked - don't need to do it again.
|
||||||
|
var dequeued = _pendingManualDsConsumptions.Dequeue();
|
||||||
|
Debug.Assert(dequeued.Fence == pds.Fence);
|
||||||
|
pds.Fence.Put();
|
||||||
|
|
||||||
|
var span = CollectionsMarshal.AsSpan(_manualDsCache[dequeued.SetIndex]);
|
||||||
|
ref var entry = ref span[dequeued.CacheIndex];
|
||||||
|
entry.CbRefMask &= ~(1u << dequeued.CommandBufferIndex);
|
||||||
|
|
||||||
|
if (!entry.InUse && entry.CbRefMask == 0)
|
||||||
|
{
|
||||||
|
// If not in use by any array, and not bound to any command buffer, the descriptor set can be re-used immediately.
|
||||||
|
(_freeManualDsCacheEntries[dequeued.SetIndex] ??= new()).Enqueue(dequeued.CacheIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void ReleaseManualDescriptorSetCollection(int setIndex, int cacheIndex)
|
public void ReleaseManualDescriptorSetCollection(int setIndex, int cacheIndex)
|
||||||
{
|
{
|
||||||
var list = _manualDsCache[setIndex];
|
var list = _manualDsCache[setIndex];
|
||||||
var span = CollectionsMarshal.AsSpan(list);
|
var span = CollectionsMarshal.AsSpan(list);
|
||||||
|
|
||||||
span[cacheIndex].InUse = false;
|
span[cacheIndex].InUse = false;
|
||||||
|
|
||||||
|
if (span[cacheIndex].CbRefMask == 0)
|
||||||
|
{
|
||||||
|
// This is no longer in use by any array, so if not bound to any command buffer, the descriptor set can be re-used immediately.
|
||||||
|
(_freeManualDsCacheEntries[setIndex] ??= new()).Enqueue(cacheIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Span<DescriptorPoolSize> GetDescriptorPoolSizes(Span<DescriptorPoolSize> output, ResourceDescriptorCollection setDescriptor, uint multiplier)
|
private static Span<DescriptorPoolSize> GetDescriptorPoolSizes(Span<DescriptorPoolSize> output, ResourceDescriptorCollection setDescriptor, uint multiplier)
|
||||||
|
@ -291,6 +366,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
_gd.Api.DestroyDescriptorSetLayout(_device, DescriptorSetLayouts[i], null);
|
_gd.Api.DestroyDescriptorSetLayout(_device, DescriptorSetLayouts[i], null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (_pendingManualDsConsumptions.TryDequeue(out var pds))
|
||||||
|
{
|
||||||
|
pds.Fence.Put();
|
||||||
|
}
|
||||||
|
|
||||||
_descriptorSetManager.Dispose();
|
_descriptorSetManager.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
|
record struct ResourceLayouts(DescriptorSetLayout[] DescriptorSetLayouts, bool[] DescriptorSetLayoutsUpdateAfterBind, PipelineLayout PipelineLayout);
|
||||||
|
|
||||||
static class PipelineLayoutFactory
|
static class PipelineLayoutFactory
|
||||||
{
|
{
|
||||||
public static unsafe (DescriptorSetLayout[], PipelineLayout) Create(
|
public static unsafe ResourceLayouts Create(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
Device device,
|
Device device,
|
||||||
ReadOnlyCollection<ResourceDescriptorCollection> setDescriptors,
|
ReadOnlyCollection<ResourceDescriptorCollection> setDescriptors,
|
||||||
bool usePushDescriptors)
|
bool usePushDescriptors)
|
||||||
{
|
{
|
||||||
DescriptorSetLayout[] layouts = new DescriptorSetLayout[setDescriptors.Count];
|
DescriptorSetLayout[] layouts = new DescriptorSetLayout[setDescriptors.Count];
|
||||||
|
bool[] updateAfterBindFlags = new bool[setDescriptors.Count];
|
||||||
|
|
||||||
bool isMoltenVk = gd.IsMoltenVk;
|
bool isMoltenVk = gd.IsMoltenVk;
|
||||||
|
|
||||||
|
@ -32,10 +37,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
DescriptorSetLayoutBinding[] layoutBindings = new DescriptorSetLayoutBinding[rdc.Descriptors.Count];
|
DescriptorSetLayoutBinding[] layoutBindings = new DescriptorSetLayoutBinding[rdc.Descriptors.Count];
|
||||||
|
|
||||||
|
bool hasArray = false;
|
||||||
|
|
||||||
for (int descIndex = 0; descIndex < rdc.Descriptors.Count; descIndex++)
|
for (int descIndex = 0; descIndex < rdc.Descriptors.Count; descIndex++)
|
||||||
{
|
{
|
||||||
ResourceDescriptor descriptor = rdc.Descriptors[descIndex];
|
ResourceDescriptor descriptor = rdc.Descriptors[descIndex];
|
||||||
|
|
||||||
ResourceStages stages = descriptor.Stages;
|
ResourceStages stages = descriptor.Stages;
|
||||||
|
|
||||||
if (descriptor.Type == ResourceType.StorageBuffer && isMoltenVk)
|
if (descriptor.Type == ResourceType.StorageBuffer && isMoltenVk)
|
||||||
|
@ -52,16 +58,37 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
DescriptorCount = (uint)descriptor.Count,
|
DescriptorCount = (uint)descriptor.Count,
|
||||||
StageFlags = stages.Convert(),
|
StageFlags = stages.Convert(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (descriptor.Count > 1)
|
||||||
|
{
|
||||||
|
hasArray = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fixed (DescriptorSetLayoutBinding* pLayoutBindings = layoutBindings)
|
fixed (DescriptorSetLayoutBinding* pLayoutBindings = layoutBindings)
|
||||||
{
|
{
|
||||||
|
DescriptorSetLayoutCreateFlags flags = DescriptorSetLayoutCreateFlags.None;
|
||||||
|
|
||||||
|
if (usePushDescriptors && setIndex == 0)
|
||||||
|
{
|
||||||
|
flags = DescriptorSetLayoutCreateFlags.PushDescriptorBitKhr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gd.Vendor == Vendor.Intel && hasArray)
|
||||||
|
{
|
||||||
|
// Some vendors (like Intel) have low per-stage limits.
|
||||||
|
// We must set the flag if we exceed those limits.
|
||||||
|
flags |= DescriptorSetLayoutCreateFlags.UpdateAfterBindPoolBit;
|
||||||
|
|
||||||
|
updateAfterBindFlags[setIndex] = true;
|
||||||
|
}
|
||||||
|
|
||||||
var descriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo
|
var descriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.DescriptorSetLayoutCreateInfo,
|
SType = StructureType.DescriptorSetLayoutCreateInfo,
|
||||||
PBindings = pLayoutBindings,
|
PBindings = pLayoutBindings,
|
||||||
BindingCount = (uint)layoutBindings.Length,
|
BindingCount = (uint)layoutBindings.Length,
|
||||||
Flags = usePushDescriptors && setIndex == 0 ? DescriptorSetLayoutCreateFlags.PushDescriptorBitKhr : DescriptorSetLayoutCreateFlags.None,
|
Flags = flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateDescriptorSetLayout(device, descriptorSetLayoutCreateInfo, null, out layouts[setIndex]).ThrowOnError();
|
gd.Api.CreateDescriptorSetLayout(device, descriptorSetLayoutCreateInfo, null, out layouts[setIndex]).ThrowOnError();
|
||||||
|
@ -82,7 +109,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError();
|
gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (layouts, layout);
|
return new ResourceLayouts(layouts, updateAfterBindFlags, layout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,244 +71,232 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
set => Internal.Id4 = (Internal.Id4 & 0xFFFFFFFF) | ((ulong)value << 32);
|
set => Internal.Id4 = (Internal.Id4 & 0xFFFFFFFF) | ((ulong)value << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float MinDepthBounds
|
|
||||||
{
|
|
||||||
readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id5 >> 0) & 0xFFFFFFFF));
|
|
||||||
set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFFF00000000) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float MaxDepthBounds
|
|
||||||
{
|
|
||||||
readonly get => BitConverter.Int32BitsToSingle((int)((Internal.Id5 >> 32) & 0xFFFFFFFF));
|
|
||||||
set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFFF) | ((ulong)(uint)BitConverter.SingleToInt32Bits(value) << 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PolygonMode PolygonMode
|
public PolygonMode PolygonMode
|
||||||
{
|
{
|
||||||
readonly get => (PolygonMode)((Internal.Id6 >> 0) & 0x3FFFFFFF);
|
readonly get => (PolygonMode)((Internal.Id5 >> 0) & 0x3FFFFFFF);
|
||||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFC0000000) | ((ulong)value << 0);
|
set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFFFC0000000) | ((ulong)value << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint StagesCount
|
public uint StagesCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id6 >> 30) & 0xFF);
|
readonly get => (byte)((Internal.Id5 >> 30) & 0xFF);
|
||||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30);
|
set => Internal.Id5 = (Internal.Id5 & 0xFFFFFFC03FFFFFFF) | ((ulong)value << 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint VertexAttributeDescriptionsCount
|
public uint VertexAttributeDescriptionsCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id6 >> 38) & 0xFF);
|
readonly get => (byte)((Internal.Id5 >> 38) & 0xFF);
|
||||||
set => Internal.Id6 = (Internal.Id6 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38);
|
set => Internal.Id5 = (Internal.Id5 & 0xFFFFC03FFFFFFFFF) | ((ulong)value << 38);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint VertexBindingDescriptionsCount
|
public uint VertexBindingDescriptionsCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id6 >> 46) & 0xFF);
|
readonly get => (byte)((Internal.Id5 >> 46) & 0xFF);
|
||||||
set => Internal.Id6 = (Internal.Id6 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46);
|
set => Internal.Id5 = (Internal.Id5 & 0xFFC03FFFFFFFFFFF) | ((ulong)value << 46);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ViewportsCount
|
public uint ViewportsCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id6 >> 54) & 0xFF);
|
readonly get => (byte)((Internal.Id5 >> 54) & 0xFF);
|
||||||
set => Internal.Id6 = (Internal.Id6 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54);
|
set => Internal.Id5 = (Internal.Id5 & 0xC03FFFFFFFFFFFFF) | ((ulong)value << 54);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ScissorsCount
|
public uint ScissorsCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id7 >> 0) & 0xFF);
|
readonly get => (byte)((Internal.Id6 >> 0) & 0xFF);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFFFFF00) | ((ulong)value << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ColorBlendAttachmentStateCount
|
public uint ColorBlendAttachmentStateCount
|
||||||
{
|
{
|
||||||
readonly get => (byte)((Internal.Id7 >> 8) & 0xFF);
|
readonly get => (byte)((Internal.Id6 >> 8) & 0xFF);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFFF00FF) | ((ulong)value << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrimitiveTopology Topology
|
public PrimitiveTopology Topology
|
||||||
{
|
{
|
||||||
readonly get => (PrimitiveTopology)((Internal.Id7 >> 16) & 0xF);
|
readonly get => (PrimitiveTopology)((Internal.Id6 >> 16) & 0xF);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFFF0FFFF) | ((ulong)value << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LogicOp LogicOp
|
public LogicOp LogicOp
|
||||||
{
|
{
|
||||||
readonly get => (LogicOp)((Internal.Id7 >> 20) & 0xF);
|
readonly get => (LogicOp)((Internal.Id6 >> 20) & 0xF);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFFF0FFFFF) | ((ulong)value << 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompareOp DepthCompareOp
|
public CompareOp DepthCompareOp
|
||||||
{
|
{
|
||||||
readonly get => (CompareOp)((Internal.Id7 >> 24) & 0x7);
|
readonly get => (CompareOp)((Internal.Id6 >> 24) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFF8FFFFFF) | ((ulong)value << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilFrontFailOp
|
public StencilOp StencilFrontFailOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 27) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 27) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFFC7FFFFFF) | ((ulong)value << 27);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilFrontPassOp
|
public StencilOp StencilFrontPassOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 30) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 30) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFFE3FFFFFFF) | ((ulong)value << 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilFrontDepthFailOp
|
public StencilOp StencilFrontDepthFailOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 33) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 33) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFFF1FFFFFFFF) | ((ulong)value << 33);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompareOp StencilFrontCompareOp
|
public CompareOp StencilFrontCompareOp
|
||||||
{
|
{
|
||||||
readonly get => (CompareOp)((Internal.Id7 >> 36) & 0x7);
|
readonly get => (CompareOp)((Internal.Id6 >> 36) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFF8FFFFFFFFF) | ((ulong)value << 36);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilBackFailOp
|
public StencilOp StencilBackFailOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 39) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 39) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFFC7FFFFFFFFF) | ((ulong)value << 39);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilBackPassOp
|
public StencilOp StencilBackPassOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 42) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 42) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFFE3FFFFFFFFFF) | ((ulong)value << 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StencilOp StencilBackDepthFailOp
|
public StencilOp StencilBackDepthFailOp
|
||||||
{
|
{
|
||||||
readonly get => (StencilOp)((Internal.Id7 >> 45) & 0x7);
|
readonly get => (StencilOp)((Internal.Id6 >> 45) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFFF1FFFFFFFFFFF) | ((ulong)value << 45);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompareOp StencilBackCompareOp
|
public CompareOp StencilBackCompareOp
|
||||||
{
|
{
|
||||||
readonly get => (CompareOp)((Internal.Id7 >> 48) & 0x7);
|
readonly get => (CompareOp)((Internal.Id6 >> 48) & 0x7);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFF8FFFFFFFFFFFF) | ((ulong)value << 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CullModeFlags CullMode
|
public CullModeFlags CullMode
|
||||||
{
|
{
|
||||||
readonly get => (CullModeFlags)((Internal.Id7 >> 51) & 0x3);
|
readonly get => (CullModeFlags)((Internal.Id6 >> 51) & 0x3);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFE7FFFFFFFFFFFF) | ((ulong)value << 51);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PrimitiveRestartEnable
|
public bool PrimitiveRestartEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 53) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 53) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFDFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 53);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthClampEnable
|
public bool DepthClampEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 54) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 54) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54);
|
set => Internal.Id6 = (Internal.Id6 & 0xFFBFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 54);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RasterizerDiscardEnable
|
public bool RasterizerDiscardEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 55) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 55) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55);
|
set => Internal.Id6 = (Internal.Id6 & 0xFF7FFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 55);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FrontFace FrontFace
|
public FrontFace FrontFace
|
||||||
{
|
{
|
||||||
readonly get => (FrontFace)((Internal.Id7 >> 56) & 0x1);
|
readonly get => (FrontFace)((Internal.Id6 >> 56) & 0x1);
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56);
|
set => Internal.Id6 = (Internal.Id6 & 0xFEFFFFFFFFFFFFFF) | ((ulong)value << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthBiasEnable
|
public bool DepthBiasEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 57) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 57) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57);
|
set => Internal.Id6 = (Internal.Id6 & 0xFDFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 57);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthTestEnable
|
public bool DepthTestEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 58) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 58) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58);
|
set => Internal.Id6 = (Internal.Id6 & 0xFBFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 58);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthWriteEnable
|
public bool DepthWriteEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 59) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 59) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59);
|
set => Internal.Id6 = (Internal.Id6 & 0xF7FFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 59);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthBoundsTestEnable
|
public bool DepthBoundsTestEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 60) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 60) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60);
|
set => Internal.Id6 = (Internal.Id6 & 0xEFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool StencilTestEnable
|
public bool StencilTestEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 61) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 61) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61);
|
set => Internal.Id6 = (Internal.Id6 & 0xDFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 61);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool LogicOpEnable
|
public bool LogicOpEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 62) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 62) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62);
|
set => Internal.Id6 = (Internal.Id6 & 0xBFFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 62);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasDepthStencil
|
public bool HasDepthStencil
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id7 >> 63) & 0x1) != 0UL;
|
readonly get => ((Internal.Id6 >> 63) & 0x1) != 0UL;
|
||||||
set => Internal.Id7 = (Internal.Id7 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63);
|
set => Internal.Id6 = (Internal.Id6 & 0x7FFFFFFFFFFFFFFF) | ((value ? 1UL : 0UL) << 63);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint PatchControlPoints
|
public uint PatchControlPoints
|
||||||
{
|
{
|
||||||
readonly get => (uint)((Internal.Id8 >> 0) & 0xFFFFFFFF);
|
readonly get => (uint)((Internal.Id7 >> 0) & 0xFFFFFFFF);
|
||||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFF00000000) | ((ulong)value << 0);
|
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF00000000) | ((ulong)value << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint SamplesCount
|
public uint SamplesCount
|
||||||
{
|
{
|
||||||
readonly get => (uint)((Internal.Id8 >> 32) & 0xFFFFFFFF);
|
readonly get => (uint)((Internal.Id7 >> 32) & 0xFFFFFFFF);
|
||||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFF) | ((ulong)value << 32);
|
set => Internal.Id7 = (Internal.Id7 & 0xFFFFFFFF) | ((ulong)value << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AlphaToCoverageEnable
|
public bool AlphaToCoverageEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id9 >> 0) & 0x1) != 0UL;
|
readonly get => ((Internal.Id8 >> 0) & 0x1) != 0UL;
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFE) | ((value ? 1UL : 0UL) << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AlphaToOneEnable
|
public bool AlphaToOneEnable
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id9 >> 1) & 0x1) != 0UL;
|
readonly get => ((Internal.Id8 >> 1) & 0x1) != 0UL;
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AdvancedBlendSrcPreMultiplied
|
public bool AdvancedBlendSrcPreMultiplied
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id9 >> 2) & 0x1) != 0UL;
|
readonly get => ((Internal.Id8 >> 2) & 0x1) != 0UL;
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFB) | ((value ? 1UL : 0UL) << 2);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFFB) | ((value ? 1UL : 0UL) << 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AdvancedBlendDstPreMultiplied
|
public bool AdvancedBlendDstPreMultiplied
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id9 >> 3) & 0x1) != 0UL;
|
readonly get => ((Internal.Id8 >> 3) & 0x1) != 0UL;
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFF7) | ((value ? 1UL : 0UL) << 3);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFF7) | ((value ? 1UL : 0UL) << 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlendOverlapEXT AdvancedBlendOverlap
|
public BlendOverlapEXT AdvancedBlendOverlap
|
||||||
{
|
{
|
||||||
readonly get => (BlendOverlapEXT)((Internal.Id9 >> 4) & 0x3);
|
readonly get => (BlendOverlapEXT)((Internal.Id8 >> 4) & 0x3);
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DepthMode
|
public bool DepthMode
|
||||||
{
|
{
|
||||||
readonly get => ((Internal.Id9 >> 6) & 0x1) != 0UL;
|
readonly get => ((Internal.Id8 >> 6) & 0x1) != 0UL;
|
||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasTessellationControlShader;
|
public bool HasTessellationControlShader;
|
||||||
|
@ -408,8 +396,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
|
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
|
||||||
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0])
|
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0])
|
||||||
fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0])
|
fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0])
|
||||||
fixed (Viewport* pViewports = &Internal.Viewports[0])
|
|
||||||
fixed (Rect2D* pScissors = &Internal.Scissors[0])
|
|
||||||
fixed (PipelineColorBlendAttachmentState* pColorBlendAttachmentState = &Internal.ColorBlendAttachmentState[0])
|
fixed (PipelineColorBlendAttachmentState* pColorBlendAttachmentState = &Internal.ColorBlendAttachmentState[0])
|
||||||
{
|
{
|
||||||
var vertexInputState = new PipelineVertexInputStateCreateInfo
|
var vertexInputState = new PipelineVertexInputStateCreateInfo
|
||||||
|
@ -472,18 +458,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
CullMode = CullMode,
|
CullMode = CullMode,
|
||||||
FrontFace = FrontFace,
|
FrontFace = FrontFace,
|
||||||
DepthBiasEnable = DepthBiasEnable,
|
DepthBiasEnable = DepthBiasEnable,
|
||||||
DepthBiasClamp = DepthBiasClamp,
|
|
||||||
DepthBiasConstantFactor = DepthBiasConstantFactor,
|
|
||||||
DepthBiasSlopeFactor = DepthBiasSlopeFactor,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var viewportState = new PipelineViewportStateCreateInfo
|
var viewportState = new PipelineViewportStateCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.PipelineViewportStateCreateInfo,
|
SType = StructureType.PipelineViewportStateCreateInfo,
|
||||||
ViewportCount = ViewportsCount,
|
ViewportCount = ViewportsCount,
|
||||||
PViewports = pViewports,
|
|
||||||
ScissorCount = ScissorsCount,
|
ScissorCount = ScissorsCount,
|
||||||
PScissors = pScissors,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (gd.Capabilities.SupportsDepthClipControl)
|
if (gd.Capabilities.SupportsDepthClipControl)
|
||||||
|
@ -511,19 +492,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
StencilFrontFailOp,
|
StencilFrontFailOp,
|
||||||
StencilFrontPassOp,
|
StencilFrontPassOp,
|
||||||
StencilFrontDepthFailOp,
|
StencilFrontDepthFailOp,
|
||||||
StencilFrontCompareOp,
|
StencilFrontCompareOp);
|
||||||
StencilFrontCompareMask,
|
|
||||||
StencilFrontWriteMask,
|
|
||||||
StencilFrontReference);
|
|
||||||
|
|
||||||
var stencilBack = new StencilOpState(
|
var stencilBack = new StencilOpState(
|
||||||
StencilBackFailOp,
|
StencilBackFailOp,
|
||||||
StencilBackPassOp,
|
StencilBackPassOp,
|
||||||
StencilBackDepthFailOp,
|
StencilBackDepthFailOp,
|
||||||
StencilBackCompareOp,
|
StencilBackCompareOp);
|
||||||
StencilBackCompareMask,
|
|
||||||
StencilBackWriteMask,
|
|
||||||
StencilBackReference);
|
|
||||||
|
|
||||||
var depthStencilState = new PipelineDepthStencilStateCreateInfo
|
var depthStencilState = new PipelineDepthStencilStateCreateInfo
|
||||||
{
|
{
|
||||||
|
@ -531,12 +506,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
DepthTestEnable = DepthTestEnable,
|
DepthTestEnable = DepthTestEnable,
|
||||||
DepthWriteEnable = DepthWriteEnable,
|
DepthWriteEnable = DepthWriteEnable,
|
||||||
DepthCompareOp = DepthCompareOp,
|
DepthCompareOp = DepthCompareOp,
|
||||||
DepthBoundsTestEnable = DepthBoundsTestEnable,
|
DepthBoundsTestEnable = false,
|
||||||
StencilTestEnable = StencilTestEnable,
|
StencilTestEnable = StencilTestEnable,
|
||||||
Front = stencilFront,
|
Front = stencilFront,
|
||||||
Back = stencilBack,
|
Back = stencilBack,
|
||||||
MinDepthBounds = MinDepthBounds,
|
|
||||||
MaxDepthBounds = MaxDepthBounds,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint blendEnables = 0;
|
uint blendEnables = 0;
|
||||||
|
@ -591,22 +564,21 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
}
|
}
|
||||||
|
|
||||||
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
||||||
int dynamicStatesCount = supportsExtDynamicState ? 9 : 8;
|
int dynamicStatesCount = supportsExtDynamicState ? 8 : 7;
|
||||||
|
|
||||||
DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
|
DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
|
||||||
|
|
||||||
dynamicStates[0] = DynamicState.Viewport;
|
dynamicStates[0] = DynamicState.Viewport;
|
||||||
dynamicStates[1] = DynamicState.Scissor;
|
dynamicStates[1] = DynamicState.Scissor;
|
||||||
dynamicStates[2] = DynamicState.DepthBias;
|
dynamicStates[2] = DynamicState.DepthBias;
|
||||||
dynamicStates[3] = DynamicState.DepthBounds;
|
dynamicStates[3] = DynamicState.StencilCompareMask;
|
||||||
dynamicStates[4] = DynamicState.StencilCompareMask;
|
dynamicStates[4] = DynamicState.StencilWriteMask;
|
||||||
dynamicStates[5] = DynamicState.StencilWriteMask;
|
dynamicStates[5] = DynamicState.StencilReference;
|
||||||
dynamicStates[6] = DynamicState.StencilReference;
|
dynamicStates[6] = DynamicState.BlendConstants;
|
||||||
dynamicStates[7] = DynamicState.BlendConstants;
|
|
||||||
|
|
||||||
if (supportsExtDynamicState)
|
if (supportsExtDynamicState)
|
||||||
{
|
{
|
||||||
dynamicStates[8] = DynamicState.VertexInputBindingStrideExt;
|
dynamicStates[7] = DynamicState.VertexInputBindingStrideExt;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo
|
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo
|
||||||
|
@ -632,7 +604,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
PDynamicState = &pipelineDynamicStateCreateInfo,
|
PDynamicState = &pipelineDynamicStateCreateInfo,
|
||||||
Layout = PipelineLayout,
|
Layout = PipelineLayout,
|
||||||
RenderPass = renderPass,
|
RenderPass = renderPass,
|
||||||
BasePipelineIndex = -1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Result result = gd.Api.CreateGraphicsPipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle);
|
Result result = gd.Api.CreateGraphicsPipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle);
|
||||||
|
|
|
@ -17,20 +17,17 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
public ulong Id4;
|
public ulong Id4;
|
||||||
public ulong Id5;
|
public ulong Id5;
|
||||||
public ulong Id6;
|
public ulong Id6;
|
||||||
|
|
||||||
public ulong Id7;
|
public ulong Id7;
|
||||||
|
|
||||||
public ulong Id8;
|
public ulong Id8;
|
||||||
public ulong Id9;
|
|
||||||
|
|
||||||
private readonly uint VertexAttributeDescriptionsCount => (byte)((Id6 >> 38) & 0xFF);
|
private readonly uint VertexAttributeDescriptionsCount => (byte)((Id5 >> 38) & 0xFF);
|
||||||
private readonly uint VertexBindingDescriptionsCount => (byte)((Id6 >> 46) & 0xFF);
|
private readonly uint VertexBindingDescriptionsCount => (byte)((Id5 >> 46) & 0xFF);
|
||||||
private readonly uint ColorBlendAttachmentStateCount => (byte)((Id7 >> 8) & 0xFF);
|
private readonly uint ColorBlendAttachmentStateCount => (byte)((Id6 >> 8) & 0xFF);
|
||||||
private readonly bool HasDepthStencil => ((Id7 >> 63) & 0x1) != 0UL;
|
private readonly bool HasDepthStencil => ((Id6 >> 63) & 0x1) != 0UL;
|
||||||
|
|
||||||
public Array32<VertexInputAttributeDescription> VertexAttributeDescriptions;
|
public Array32<VertexInputAttributeDescription> VertexAttributeDescriptions;
|
||||||
public Array33<VertexInputBindingDescription> VertexBindingDescriptions;
|
public Array33<VertexInputBindingDescription> VertexBindingDescriptions;
|
||||||
public Array16<Viewport> Viewports;
|
|
||||||
public Array16<Rect2D> Scissors;
|
|
||||||
public Array8<PipelineColorBlendAttachmentState> ColorBlendAttachmentState;
|
public Array8<PipelineColorBlendAttachmentState> ColorBlendAttachmentState;
|
||||||
public Array9<Format> AttachmentFormats;
|
public Array9<Format> AttachmentFormats;
|
||||||
public uint AttachmentIntegerFormatMask;
|
public uint AttachmentIntegerFormatMask;
|
||||||
|
@ -45,7 +42,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
if (!Unsafe.As<ulong, Vector256<byte>>(ref Id0).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id0)) ||
|
if (!Unsafe.As<ulong, Vector256<byte>>(ref Id0).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id0)) ||
|
||||||
!Unsafe.As<ulong, Vector256<byte>>(ref Id4).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id4)) ||
|
!Unsafe.As<ulong, Vector256<byte>>(ref Id4).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id4)) ||
|
||||||
!Unsafe.As<ulong, Vector128<byte>>(ref Id8).Equals(Unsafe.As<ulong, Vector128<byte>>(ref other.Id8)))
|
!Unsafe.As<ulong, Vector128<byte>>(ref Id7).Equals(Unsafe.As<ulong, Vector128<byte>>(ref other.Id7)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -88,8 +85,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
Id5 * 23 ^
|
Id5 * 23 ^
|
||||||
Id6 * 23 ^
|
Id6 * 23 ^
|
||||||
Id7 * 23 ^
|
Id7 * 23 ^
|
||||||
Id8 * 23 ^
|
Id8 * 23;
|
||||||
Id9 * 23;
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)VertexAttributeDescriptionsCount; i++)
|
for (int i = 0; i < (int)VertexAttributeDescriptionsCount; i++)
|
||||||
{
|
{
|
||||||
|
|
74
src/Ryujinx.Graphics.Vulkan/ResourceArray.cs
Normal file
74
src/Ryujinx.Graphics.Vulkan/ResourceArray.cs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
using Silk.NET.Vulkan;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
|
{
|
||||||
|
class ResourceArray : IDisposable
|
||||||
|
{
|
||||||
|
private DescriptorSet[] _cachedDescriptorSets;
|
||||||
|
|
||||||
|
private ShaderCollection _cachedDscProgram;
|
||||||
|
private int _cachedDscSetIndex;
|
||||||
|
private int _cachedDscIndex;
|
||||||
|
|
||||||
|
private int _bindCount;
|
||||||
|
|
||||||
|
protected void SetDirty(VulkanRenderer gd)
|
||||||
|
{
|
||||||
|
ReleaseDescriptorSet();
|
||||||
|
|
||||||
|
if (_bindCount != 0)
|
||||||
|
{
|
||||||
|
gd.PipelineInternal.ForceTextureDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetCachedDescriptorSets(CommandBufferScoped cbs, ShaderCollection program, int setIndex, out DescriptorSet[] sets)
|
||||||
|
{
|
||||||
|
if (_cachedDescriptorSets != null)
|
||||||
|
{
|
||||||
|
_cachedDscProgram.UpdateManualDescriptorSetCollectionOwnership(cbs, _cachedDscSetIndex, _cachedDscIndex);
|
||||||
|
|
||||||
|
sets = _cachedDescriptorSets;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dsc = program.GetNewManualDescriptorSetCollection(cbs, setIndex, out _cachedDscIndex).Get(cbs);
|
||||||
|
|
||||||
|
sets = dsc.GetSets();
|
||||||
|
|
||||||
|
_cachedDescriptorSets = sets;
|
||||||
|
_cachedDscProgram = program;
|
||||||
|
_cachedDscSetIndex = setIndex;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncrementBindCount()
|
||||||
|
{
|
||||||
|
_bindCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecrementBindCount()
|
||||||
|
{
|
||||||
|
int newBindCount = --_bindCount;
|
||||||
|
Debug.Assert(newBindCount >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReleaseDescriptorSet()
|
||||||
|
{
|
||||||
|
if (_cachedDescriptorSets != null)
|
||||||
|
{
|
||||||
|
_cachedDscProgram.ReleaseManualDescriptorSetCollection(_cachedDscSetIndex, _cachedDscIndex);
|
||||||
|
_cachedDescriptorSets = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
ReleaseDescriptorSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -604,9 +604,14 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
return _plce.GetNewDescriptorSetCollection(setIndex, out isNew);
|
return _plce.GetNewDescriptorSetCollection(setIndex, out isNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Auto<DescriptorSetCollection> GetNewManualDescriptorSetCollection(int commandBufferIndex, int setIndex, out int cacheIndex)
|
public Auto<DescriptorSetCollection> GetNewManualDescriptorSetCollection(CommandBufferScoped cbs, int setIndex, out int cacheIndex)
|
||||||
{
|
{
|
||||||
return _plce.GetNewManualDescriptorSetCollection(commandBufferIndex, setIndex, out cacheIndex);
|
return _plce.GetNewManualDescriptorSetCollection(cbs, setIndex, out cacheIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateManualDescriptorSetCollectionOwnership(CommandBufferScoped cbs, int setIndex, int cacheIndex)
|
||||||
|
{
|
||||||
|
_plce.UpdateManualDescriptorSetCollectionOwnership(cbs, setIndex, cacheIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReleaseManualDescriptorSetCollection(int setIndex, int cacheIndex)
|
public void ReleaseManualDescriptorSetCollection(int setIndex, int cacheIndex)
|
||||||
|
|
|
@ -2,11 +2,10 @@ using Ryujinx.Graphics.GAL;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
class TextureArray : ITextureArray
|
class TextureArray : ResourceArray, ITextureArray
|
||||||
{
|
{
|
||||||
private readonly VulkanRenderer _gd;
|
private readonly VulkanRenderer _gd;
|
||||||
|
|
||||||
|
@ -25,19 +24,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
private HashSet<TextureStorage> _storages;
|
private HashSet<TextureStorage> _storages;
|
||||||
|
|
||||||
private DescriptorSet[] _cachedDescriptorSets;
|
|
||||||
|
|
||||||
private int _cachedCommandBufferIndex;
|
private int _cachedCommandBufferIndex;
|
||||||
private int _cachedSubmissionCount;
|
private int _cachedSubmissionCount;
|
||||||
|
|
||||||
private ShaderCollection _cachedDscProgram;
|
|
||||||
private int _cachedDscSetIndex;
|
|
||||||
private int _cachedDscIndex;
|
|
||||||
|
|
||||||
private readonly bool _isBuffer;
|
private readonly bool _isBuffer;
|
||||||
|
|
||||||
private int _bindCount;
|
|
||||||
|
|
||||||
public TextureArray(VulkanRenderer gd, int size, bool isBuffer)
|
public TextureArray(VulkanRenderer gd, int size, bool isBuffer)
|
||||||
{
|
{
|
||||||
_gd = gd;
|
_gd = gd;
|
||||||
|
@ -113,12 +104,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
_cachedCommandBufferIndex = -1;
|
_cachedCommandBufferIndex = -1;
|
||||||
_storages = null;
|
_storages = null;
|
||||||
_cachedDescriptorSets = null;
|
SetDirty(_gd);
|
||||||
|
|
||||||
if (_bindCount != 0)
|
|
||||||
{
|
|
||||||
_gd.PipelineInternal.ForceTextureDirty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
|
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
|
||||||
|
@ -211,7 +197,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
TextureView dummyTexture,
|
TextureView dummyTexture,
|
||||||
SamplerHolder dummySampler)
|
SamplerHolder dummySampler)
|
||||||
{
|
{
|
||||||
if (_cachedDescriptorSets != null)
|
if (TryGetCachedDescriptorSets(cbs, program, setIndex, out DescriptorSet[] sets))
|
||||||
{
|
{
|
||||||
// We still need to ensure the current command buffer holds a reference to all used textures.
|
// We still need to ensure the current command buffer holds a reference to all used textures.
|
||||||
|
|
||||||
|
@ -224,12 +210,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
GetBufferViews(cbs);
|
GetBufferViews(cbs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _cachedDescriptorSets;
|
return sets;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cachedDscProgram?.ReleaseManualDescriptorSetCollection(_cachedDscSetIndex, _cachedDscIndex);
|
|
||||||
var dsc = program.GetNewManualDescriptorSetCollection(cbs.CommandBufferIndex, setIndex, out _cachedDscIndex).Get(cbs);
|
|
||||||
|
|
||||||
DescriptorSetTemplate template = program.Templates[setIndex];
|
DescriptorSetTemplate template = program.Templates[setIndex];
|
||||||
|
|
||||||
DescriptorSetTemplateWriter tu = templateUpdater.Begin(template);
|
DescriptorSetTemplateWriter tu = templateUpdater.Begin(template);
|
||||||
|
@ -243,24 +226,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
tu.Push(GetBufferViews(cbs));
|
tu.Push(GetBufferViews(cbs));
|
||||||
}
|
}
|
||||||
|
|
||||||
var sets = dsc.GetSets();
|
|
||||||
templateUpdater.Commit(_gd, device, sets[0]);
|
templateUpdater.Commit(_gd, device, sets[0]);
|
||||||
_cachedDescriptorSets = sets;
|
|
||||||
_cachedDscProgram = program;
|
|
||||||
_cachedDscSetIndex = setIndex;
|
|
||||||
|
|
||||||
return sets;
|
return sets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void IncrementBindCount()
|
|
||||||
{
|
|
||||||
_bindCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DecrementBindCount()
|
|
||||||
{
|
|
||||||
int newBindCount = --_bindCount;
|
|
||||||
Debug.Assert(newBindCount >= 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue