diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Shader')
8 files changed, 90 insertions, 29 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs index 17639ca1..537cead0 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheGpuAccessor.cs @@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache ShaderSpecializationState oldSpecState, ShaderSpecializationState newSpecState, ResourceCounts counts, - int stageIndex) : base(context, counts, stageIndex) + int stageIndex) : base(context, counts, stageIndex, oldSpecState.TransformFeedbackDescriptors != null) { _data = data; _cb1Data = cb1Data; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs index f35b542a..153a2e8c 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs @@ -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 = 5044; + private const uint CodeGenVersion = 5080; private const string SharedTocFileName = "shared.toc"; private const string SharedDataFileName = "shared.data"; @@ -368,7 +368,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache if (hostCode != null) { - ShaderInfo shaderInfo = ShaderInfoBuilder.BuildForCache(context, shaders, specState.PipelineState); + ShaderInfo shaderInfo = ShaderInfoBuilder.BuildForCache( + context, + shaders, + specState.PipelineState, + specState.TransformFeedbackDescriptors != null); IProgram hostProgram; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs index d80518b1..8df89824 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/ParallelDiskCacheLoader.cs @@ -491,7 +491,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache { ShaderSource[] shaderSources = new ShaderSource[compilation.TranslatedStages.Length]; - ShaderInfoBuilder shaderInfoBuilder = new ShaderInfoBuilder(_context); + ShaderInfoBuilder shaderInfoBuilder = new ShaderInfoBuilder(_context, compilation.SpecializationState.TransformFeedbackDescriptors != null); for (int index = 0; index < compilation.TranslatedStages.Length; index++) { diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs index 3e816733..5e18e61f 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs @@ -30,7 +30,7 @@ namespace Ryujinx.Graphics.Gpu.Shader GpuContext context, GpuChannel channel, GpuAccessorState state, - int stageIndex) : base(context, state.ResourceCounts, stageIndex) + int stageIndex) : base(context, state.ResourceCounts, stageIndex, state.TransformFeedbackDescriptors != null) { _isVulkan = context.Capabilities.Api == TargetApi.Vulkan; _channel = channel; @@ -44,7 +44,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <param name="context">GPU context</param> /// <param name="channel">GPU channel</param> /// <param name="state">Current GPU state</param> - public GpuAccessor(GpuContext context, GpuChannel channel, GpuAccessorState state) : base(context, state.ResourceCounts, 0) + public GpuAccessor(GpuContext context, GpuChannel channel, GpuAccessorState state) : base(context, state.ResourceCounts, 0, false) { _channel = channel; _state = state; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs index 57e79ac7..2dd7c631 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/GpuAccessorBase.cs @@ -17,40 +17,56 @@ namespace Ryujinx.Graphics.Gpu.Shader private readonly ResourceCounts _resourceCounts; private readonly int _stageIndex; + private readonly int _reservedConstantBuffers; + private readonly int _reservedStorageBuffers; + /// <summary> /// Creates a new GPU accessor. /// </summary> /// <param name="context">GPU context</param> - public GpuAccessorBase(GpuContext context, ResourceCounts resourceCounts, int stageIndex) + /// <param name="resourceCounts">Counter of GPU resources used by the shader</param> + /// <param name="stageIndex">Index of the shader stage, 0 for compute</param> + /// <param name="tfEnabled">Indicates if the current graphics shader is used with transform feedback enabled</param> + public GpuAccessorBase(GpuContext context, ResourceCounts resourceCounts, int stageIndex, bool tfEnabled) { _context = context; _resourceCounts = resourceCounts; _stageIndex = stageIndex; + + _reservedConstantBuffers = 1; // For the support buffer. + _reservedStorageBuffers = !context.Capabilities.SupportsTransformFeedback && tfEnabled ? 5 : 0; } public int QueryBindingConstantBuffer(int index) { + int binding; + if (_context.Capabilities.Api == TargetApi.Vulkan) { - // We need to start counting from 1 since binding 0 is reserved for the support uniform buffer. - return GetBindingFromIndex(index, _context.Capabilities.MaximumUniformBuffersPerStage, "Uniform buffer") + 1; + binding = GetBindingFromIndex(index, _context.Capabilities.MaximumUniformBuffersPerStage, "Uniform buffer"); } else { - return _resourceCounts.UniformBuffersCount++; + binding = _resourceCounts.UniformBuffersCount++; } + + return binding + _reservedConstantBuffers; } public int QueryBindingStorageBuffer(int index) { + int binding; + if (_context.Capabilities.Api == TargetApi.Vulkan) { - return GetBindingFromIndex(index, _context.Capabilities.MaximumStorageBuffersPerStage, "Storage buffer"); + binding = GetBindingFromIndex(index, _context.Capabilities.MaximumStorageBuffersPerStage, "Storage buffer"); } else { - return _resourceCounts.StorageBuffersCount++; + binding = _resourceCounts.StorageBuffersCount++; } + + return binding + _reservedStorageBuffers; } public int QueryBindingTexture(int index, bool isBuffer) @@ -149,6 +165,8 @@ namespace Ryujinx.Graphics.Gpu.Shader public bool QueryHostSupportsTextureShadowLod() => _context.Capabilities.SupportsTextureShadowLod; + public bool QueryHostSupportsTransformFeedback() => _context.Capabilities.SupportsTransformFeedback; + public bool QueryHostSupportsViewportIndexVertexTessellation() => _context.Capabilities.SupportsViewportIndexVertexTessellation; public bool QueryHostSupportsViewportMask() => _context.Capabilities.SupportsViewportMask; diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ResourceCounts.cs b/src/Ryujinx.Graphics.Gpu/Shader/ResourceCounts.cs index b85423cb..f495229f 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/ResourceCounts.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/ResourceCounts.cs @@ -24,13 +24,5 @@ namespace Ryujinx.Graphics.Gpu.Shader /// Total of images used by the shaders. /// </summary> public int ImagesCount; - - /// <summary> - /// Creates a new instance of the shader resource counts class. - /// </summary> - public ResourceCounts() - { - UniformBuffersCount = 1; // The first binding is reserved for the support buffer. - } } }
\ No newline at end of file diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index b7ba159a..913f6e9e 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -362,7 +362,7 @@ namespace Ryujinx.Graphics.Gpu.Shader TranslatorContext previousStage = null; - ShaderInfoBuilder infoBuilder = new ShaderInfoBuilder(_context); + ShaderInfoBuilder infoBuilder = new ShaderInfoBuilder(_context, transformFeedbackDescriptors != null); for (int stageIndex = 0; stageIndex < Constants.ShaderStages; stageIndex++) { diff --git a/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs b/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs index 3fc32d71..83d92edc 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/ShaderInfoBuilder.cs @@ -16,15 +16,24 @@ namespace Ryujinx.Graphics.Gpu.Shader private const int TextureSetIndex = 2; private const int ImageSetIndex = 3; - private const ResourceStages SupportBufferStags = + private const ResourceStages SupportBufferStages = ResourceStages.Compute | ResourceStages.Vertex | ResourceStages.Fragment; + private const ResourceStages VtgStages = + ResourceStages.Vertex | + ResourceStages.TessellationControl | + ResourceStages.TessellationEvaluation | + ResourceStages.Geometry; + private readonly GpuContext _context; private int _fragmentOutputMap; + private readonly int _reservedConstantBuffers; + private readonly int _reservedStorageBuffers; + private readonly List<ResourceDescriptor>[] _resourceDescriptors; private readonly List<ResourceUsage>[] _resourceUsages; @@ -32,7 +41,8 @@ namespace Ryujinx.Graphics.Gpu.Shader /// Creates a new shader info builder. /// </summary> /// <param name="context">GPU context that owns the shaders that will be added to the builder</param> - public ShaderInfoBuilder(GpuContext context) + /// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param> + public ShaderInfoBuilder(GpuContext context, bool tfEnabled) { _context = context; @@ -47,7 +57,22 @@ namespace Ryujinx.Graphics.Gpu.Shader _resourceUsages[index] = new(); } - AddDescriptor(SupportBufferStags, ResourceType.UniformBuffer, UniformSetIndex, 0, 1); + AddDescriptor(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1); + + _reservedConstantBuffers = 1; // For the support buffer. + + if (!context.Capabilities.SupportsTransformFeedback && tfEnabled) + { + _reservedStorageBuffers = 5; + + AddDescriptor(VtgStages, ResourceType.StorageBuffer, StorageSetIndex, 0, 5); + AddUsage(VtgStages, ResourceType.StorageBuffer, ResourceAccess.Read, StorageSetIndex, 0, 1); + AddUsage(VtgStages, ResourceType.StorageBuffer, ResourceAccess.Write, StorageSetIndex, 1, 4); + } + else + { + _reservedStorageBuffers = 0; + } } /// <summary> @@ -86,8 +111,8 @@ namespace Ryujinx.Graphics.Gpu.Shader int texturesPerStage = (int)_context.Capabilities.MaximumTexturesPerStage; int imagesPerStage = (int)_context.Capabilities.MaximumImagesPerStage; - int uniformBinding = 1 + stageIndex * uniformsPerStage; - int storageBinding = stageIndex * storagesPerStage; + int uniformBinding = _reservedConstantBuffers + stageIndex * uniformsPerStage; + int storageBinding = _reservedStorageBuffers + stageIndex * storagesPerStage; int textureBinding = stageIndex * texturesPerStage * 2; int imageBinding = stageIndex * imagesPerStage * 2; @@ -136,6 +161,23 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <summary> /// Adds buffer usage information to the list of usages. /// </summary> + /// <param name="stages">Shader stages where the resource is used</param> + /// <param name="type">Type of the resource</param> + /// <param name="access">How the resource is accessed by the shader stages where it is used</param> + /// <param name="setIndex">Descriptor set number where the resource will be bound</param> + /// <param name="binding">Binding number where the resource will be bound</param> + /// <param name="count">Number of resources bound at the binding location</param> + private void AddUsage(ResourceStages stages, ResourceType type, ResourceAccess access, int setIndex, int binding, int count) + { + for (int index = 0; index < count; index++) + { + _resourceUsages[setIndex].Add(new ResourceUsage(binding + index, type, stages, access)); + } + } + + /// <summary> + /// Adds buffer usage information to the list of usages. + /// </summary> /// <param name="buffers">Buffers to be added</param> /// <param name="stages">Stages where the buffers are used</param> /// <param name="setIndex">Descriptor set index where the buffers will be bound</param> @@ -212,10 +254,15 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <param name="context">GPU context that owns the shaders</param> /// <param name="programs">Shaders from the disk cache</param> /// <param name="pipeline">Optional pipeline for background compilation</param> + /// <param name="tfEnabled">Indicates if the graphics shader is used with transform feedback enabled</param> /// <returns>Shader information</returns> - public static ShaderInfo BuildForCache(GpuContext context, IEnumerable<CachedShaderStage> programs, ProgramPipelineState? pipeline) + public static ShaderInfo BuildForCache( + GpuContext context, + IEnumerable<CachedShaderStage> programs, + ProgramPipelineState? pipeline, + bool tfEnabled) { - ShaderInfoBuilder builder = new ShaderInfoBuilder(context); + ShaderInfoBuilder builder = new ShaderInfoBuilder(context, tfEnabled); foreach (CachedShaderStage program in programs) { @@ -237,7 +284,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// <returns>Shader information</returns> public static ShaderInfo BuildForCompute(GpuContext context, ShaderProgramInfo info, bool fromCache = false) { - ShaderInfoBuilder builder = new ShaderInfoBuilder(context); + ShaderInfoBuilder builder = new ShaderInfoBuilder(context, tfEnabled: false); builder.AddStageInfo(info); |