Compute.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using Ryujinx.Graphics.GAL;
  2. using Ryujinx.Graphics.Gpu.Image;
  3. using Ryujinx.Graphics.Gpu.Shader;
  4. using Ryujinx.Graphics.Gpu.State;
  5. using Ryujinx.Graphics.Shader;
  6. using System;
  7. using System.Runtime.InteropServices;
  8. namespace Ryujinx.Graphics.Gpu.Engine
  9. {
  10. partial class Methods
  11. {
  12. /// <summary>
  13. /// Dispatches compute work.
  14. /// </summary>
  15. /// <param name="state">Current GPU state</param>
  16. /// <param name="argument">Method call argument</param>
  17. public void Dispatch(GpuState state, int argument)
  18. {
  19. uint dispatchParamsAddress = (uint)state.Get<int>(MethodOffset.DispatchParamsAddress);
  20. var dispatchParams = _context.MemoryAccessor.Read<ComputeParams>((ulong)dispatchParamsAddress << 8);
  21. GpuVa shaderBaseAddress = state.Get<GpuVa>(MethodOffset.ShaderBaseAddress);
  22. ulong shaderGpuVa = shaderBaseAddress.Pack() + (uint)dispatchParams.ShaderOffset;
  23. // Note: A size of 0 is also invalid, the size must be at least 1.
  24. int sharedMemorySize = Math.Clamp(dispatchParams.SharedMemorySize & 0xffff, 1, _context.Capabilities.MaximumComputeSharedMemorySize);
  25. ComputeShader cs = ShaderCache.GetComputeShader(
  26. shaderGpuVa,
  27. sharedMemorySize,
  28. dispatchParams.UnpackBlockSizeX(),
  29. dispatchParams.UnpackBlockSizeY(),
  30. dispatchParams.UnpackBlockSizeZ());
  31. _context.Renderer.Pipeline.SetProgram(cs.HostProgram);
  32. var samplerPool = state.Get<PoolState>(MethodOffset.SamplerPoolState);
  33. TextureManager.SetComputeSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId, dispatchParams.SamplerIndex);
  34. var texturePool = state.Get<PoolState>(MethodOffset.TexturePoolState);
  35. TextureManager.SetComputeTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);
  36. TextureManager.SetComputeTextureBufferIndex(state.Get<int>(MethodOffset.TextureBufferIndex));
  37. ShaderProgramInfo info = cs.Shader.Program.Info;
  38. uint sbEnableMask = 0;
  39. uint ubEnableMask = dispatchParams.UnpackUniformBuffersEnableMask();
  40. for (int index = 0; index < dispatchParams.UniformBuffers.Length; index++)
  41. {
  42. if ((ubEnableMask & (1 << index)) == 0)
  43. {
  44. continue;
  45. }
  46. ulong gpuVa = dispatchParams.UniformBuffers[index].PackAddress();
  47. ulong size = dispatchParams.UniformBuffers[index].UnpackSize();
  48. BufferManager.SetComputeUniformBuffer(index, gpuVa, size);
  49. }
  50. for (int index = 0; index < info.SBuffers.Count; index++)
  51. {
  52. BufferDescriptor sb = info.SBuffers[index];
  53. sbEnableMask |= 1u << sb.Slot;
  54. ulong sbDescAddress = BufferManager.GetComputeUniformBufferAddress(0);
  55. int sbDescOffset = 0x310 + sb.Slot * 0x10;
  56. sbDescAddress += (ulong)sbDescOffset;
  57. ReadOnlySpan<byte> sbDescriptorData = _context.PhysicalMemory.GetSpan(sbDescAddress, 0x10);
  58. SbDescriptor sbDescriptor = MemoryMarshal.Cast<byte, SbDescriptor>(sbDescriptorData)[0];
  59. BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size);
  60. }
  61. ubEnableMask = 0;
  62. for (int index = 0; index < info.CBuffers.Count; index++)
  63. {
  64. ubEnableMask |= 1u << info.CBuffers[index].Slot;
  65. }
  66. BufferManager.SetComputeStorageBufferEnableMask(sbEnableMask);
  67. BufferManager.SetComputeUniformBufferEnableMask(ubEnableMask);
  68. var textureBindings = new TextureBindingInfo[info.Textures.Count];
  69. for (int index = 0; index < info.Textures.Count; index++)
  70. {
  71. var descriptor = info.Textures[index];
  72. Target target = GetTarget(descriptor.Type);
  73. if (descriptor.IsBindless)
  74. {
  75. textureBindings[index] = new TextureBindingInfo(target, descriptor.CbufOffset, descriptor.CbufSlot);
  76. }
  77. else
  78. {
  79. textureBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
  80. }
  81. }
  82. TextureManager.SetComputeTextures(textureBindings);
  83. var imageBindings = new TextureBindingInfo[info.Images.Count];
  84. for (int index = 0; index < info.Images.Count; index++)
  85. {
  86. var descriptor = info.Images[index];
  87. Target target = GetTarget(descriptor.Type);
  88. imageBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex);
  89. }
  90. TextureManager.SetComputeImages(imageBindings);
  91. BufferManager.CommitComputeBindings();
  92. TextureManager.CommitComputeBindings();
  93. _context.Renderer.Pipeline.DispatchCompute(
  94. dispatchParams.UnpackGridSizeX(),
  95. dispatchParams.UnpackGridSizeY(),
  96. dispatchParams.UnpackGridSizeZ());
  97. UpdateShaderState(state);
  98. }
  99. }
  100. }