FxaaPostProcessingEffect.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. using Ryujinx.Common;
  2. using Ryujinx.Graphics.GAL;
  3. using Ryujinx.Graphics.Shader;
  4. using Ryujinx.Graphics.Shader.Translation;
  5. using Silk.NET.Vulkan;
  6. using System;
  7. namespace Ryujinx.Graphics.Vulkan.Effects
  8. {
  9. internal partial class FxaaPostProcessingEffect : IPostProcessingEffect
  10. {
  11. private readonly VulkanRenderer _renderer;
  12. private ISampler _samplerLinear;
  13. private ShaderCollection _shaderProgram;
  14. private PipelineHelperShader _pipeline;
  15. private TextureView _texture;
  16. public FxaaPostProcessingEffect(VulkanRenderer renderer, Device device)
  17. {
  18. _renderer = renderer;
  19. _pipeline = new PipelineHelperShader(renderer, device);
  20. Initialize();
  21. }
  22. public void Dispose()
  23. {
  24. _shaderProgram.Dispose();
  25. _pipeline.Dispose();
  26. _samplerLinear.Dispose();
  27. _texture?.Dispose();
  28. }
  29. private void Initialize()
  30. {
  31. _pipeline.Initialize();
  32. var shader = EmbeddedResources.Read("Ryujinx.Graphics.Vulkan/Effects/Shaders/Fxaa.spv");
  33. var computeBindings = new ShaderBindings(
  34. new[] { 2 },
  35. Array.Empty<int>(),
  36. new[] { 1 },
  37. new[] { 0 });
  38. _samplerLinear = _renderer.CreateSampler(GAL.SamplerCreateInfo.Create(MinFilter.Linear, MagFilter.Linear));
  39. _shaderProgram = _renderer.CreateProgramWithMinimalLayout(new[]
  40. {
  41. new ShaderSource(shader, computeBindings, ShaderStage.Compute, TargetLanguage.Spirv)
  42. });
  43. }
  44. public TextureView Run(TextureView view, CommandBufferScoped cbs, int width, int height)
  45. {
  46. if (_texture == null || _texture.Width != view.Width || _texture.Height != view.Height)
  47. {
  48. _texture?.Dispose();
  49. var info = view.Info;
  50. if (view.Info.Format.IsBgr())
  51. {
  52. info = new TextureCreateInfo(info.Width,
  53. info.Height,
  54. info.Depth,
  55. info.Levels,
  56. info.Samples,
  57. info.BlockWidth,
  58. info.BlockHeight,
  59. info.BytesPerPixel,
  60. info.Format,
  61. info.DepthStencilMode,
  62. info.Target,
  63. info.SwizzleB,
  64. info.SwizzleG,
  65. info.SwizzleR,
  66. info.SwizzleA);
  67. }
  68. _texture = _renderer.CreateTexture(info, view.ScaleFactor) as TextureView;
  69. }
  70. _pipeline.SetCommandBuffer(cbs);
  71. _pipeline.SetProgram(_shaderProgram);
  72. _pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, view, _samplerLinear);
  73. ReadOnlySpan<float> resolutionBuffer = stackalloc float[] { view.Width, view.Height };
  74. int rangeSize = resolutionBuffer.Length * sizeof(float);
  75. var bufferHandle = _renderer.BufferManager.CreateWithHandle(_renderer, rangeSize);
  76. _renderer.BufferManager.SetData(bufferHandle, 0, resolutionBuffer);
  77. var bufferRanges = new BufferRange(bufferHandle, 0, rangeSize);
  78. _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(2, bufferRanges) });
  79. var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
  80. var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
  81. _pipeline.SetImage(0, _texture, GAL.Format.R8G8B8A8Unorm);
  82. _pipeline.DispatchCompute(dispatchX, dispatchY, 1);
  83. _renderer.BufferManager.Delete(bufferHandle);
  84. _pipeline.ComputeBarrier();
  85. _pipeline.Finish();
  86. return _texture;
  87. }
  88. }
  89. }