Compute.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. namespace Ryujinx.Graphics.Gpu.Engine
  8. {
  9. partial class Methods
  10. {
  11. /// <summary>
  12. /// Dispatches compute work.
  13. /// </summary>
  14. /// <param name="state">Current GPU state</param>
  15. /// <param name="argument">Method call argument</param>
  16. public void Dispatch(GpuState state, int argument)
  17. {
  18. var memoryManager = state.Channel.MemoryManager;
  19. FlushUboDirty(memoryManager);
  20. uint qmdAddress = (uint)state.Get<int>(MethodOffset.DispatchParamsAddress);
  21. var qmd = state.Channel.MemoryManager.Read<ComputeQmd>((ulong)qmdAddress << 8);
  22. GpuVa shaderBaseAddress = state.Get<GpuVa>(MethodOffset.ShaderBaseAddress);
  23. ulong shaderGpuVa = shaderBaseAddress.Pack() + (uint)qmd.ProgramOffset;
  24. int localMemorySize = qmd.ShaderLocalMemoryLowSize + qmd.ShaderLocalMemoryHighSize;
  25. int sharedMemorySize = Math.Min(qmd.SharedMemorySize, _context.Capabilities.MaximumComputeSharedMemorySize);
  26. for (int index = 0; index < Constants.TotalCpUniformBuffers; index++)
  27. {
  28. if (!qmd.ConstantBufferValid(index))
  29. {
  30. continue;
  31. }
  32. ulong gpuVa = (uint)qmd.ConstantBufferAddrLower(index) | (ulong)qmd.ConstantBufferAddrUpper(index) << 32;
  33. ulong size = (ulong)qmd.ConstantBufferSize(index);
  34. state.Channel.BufferManager.SetComputeUniformBuffer(index, gpuVa, size);
  35. }
  36. ShaderBundle cs = memoryManager.Physical.ShaderCache.GetComputeShader(
  37. state,
  38. shaderGpuVa,
  39. qmd.CtaThreadDimension0,
  40. qmd.CtaThreadDimension1,
  41. qmd.CtaThreadDimension2,
  42. localMemorySize,
  43. sharedMemorySize);
  44. _context.Renderer.Pipeline.SetProgram(cs.HostProgram);
  45. var samplerPool = state.Get<PoolState>(MethodOffset.SamplerPoolState);
  46. var texturePool = state.Get<PoolState>(MethodOffset.TexturePoolState);
  47. state.Channel.TextureManager.SetComputeSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId, qmd.SamplerIndex);
  48. state.Channel.TextureManager.SetComputeTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);
  49. state.Channel.TextureManager.SetComputeTextureBufferIndex(state.Get<int>(MethodOffset.TextureBufferIndex));
  50. ShaderProgramInfo info = cs.Shaders[0].Info;
  51. for (int index = 0; index < info.CBuffers.Count; index++)
  52. {
  53. BufferDescriptor cb = info.CBuffers[index];
  54. // NVN uses the "hardware" constant buffer for anything that is less than 8,
  55. // and those are already bound above.
  56. // Anything greater than or equal to 8 uses the emulated constant buffers.
  57. // They are emulated using global memory loads.
  58. if (cb.Slot < 8)
  59. {
  60. continue;
  61. }
  62. ulong cbDescAddress = state.Channel.BufferManager.GetComputeUniformBufferAddress(0);
  63. int cbDescOffset = 0x260 + (cb.Slot - 8) * 0x10;
  64. cbDescAddress += (ulong)cbDescOffset;
  65. SbDescriptor cbDescriptor = state.Channel.MemoryManager.Physical.Read<SbDescriptor>(cbDescAddress);
  66. state.Channel.BufferManager.SetComputeUniformBuffer(cb.Slot, cbDescriptor.PackAddress(), (uint)cbDescriptor.Size);
  67. }
  68. for (int index = 0; index < info.SBuffers.Count; index++)
  69. {
  70. BufferDescriptor sb = info.SBuffers[index];
  71. ulong sbDescAddress = state.Channel.BufferManager.GetComputeUniformBufferAddress(0);
  72. int sbDescOffset = 0x310 + sb.Slot * 0x10;
  73. sbDescAddress += (ulong)sbDescOffset;
  74. SbDescriptor sbDescriptor = state.Channel.MemoryManager.Physical.Read<SbDescriptor>(sbDescAddress);
  75. state.Channel.BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size, sb.Flags);
  76. }
  77. state.Channel.BufferManager.SetComputeStorageBufferBindings(info.SBuffers);
  78. state.Channel.BufferManager.SetComputeUniformBufferBindings(info.CBuffers);
  79. var textureBindings = new TextureBindingInfo[info.Textures.Count];
  80. for (int index = 0; index < info.Textures.Count; index++)
  81. {
  82. var descriptor = info.Textures[index];
  83. Target target = ShaderTexture.GetTarget(descriptor.Type);
  84. textureBindings[index] = new TextureBindingInfo(
  85. target,
  86. descriptor.Binding,
  87. descriptor.CbufSlot,
  88. descriptor.HandleIndex,
  89. descriptor.Flags);
  90. }
  91. state.Channel.TextureManager.SetComputeTextures(textureBindings);
  92. var imageBindings = new TextureBindingInfo[info.Images.Count];
  93. for (int index = 0; index < info.Images.Count; index++)
  94. {
  95. var descriptor = info.Images[index];
  96. Target target = ShaderTexture.GetTarget(descriptor.Type);
  97. Format format = ShaderTexture.GetFormat(descriptor.Format);
  98. imageBindings[index] = new TextureBindingInfo(
  99. target,
  100. format,
  101. descriptor.Binding,
  102. descriptor.CbufSlot,
  103. descriptor.HandleIndex,
  104. descriptor.Flags);
  105. }
  106. state.Channel.TextureManager.SetComputeImages(imageBindings);
  107. state.Channel.TextureManager.CommitComputeBindings();
  108. state.Channel.BufferManager.CommitComputeBindings();
  109. _context.Renderer.Pipeline.DispatchCompute(
  110. qmd.CtaRasterWidth,
  111. qmd.CtaRasterHeight,
  112. qmd.CtaRasterDepth);
  113. _forceShaderUpdate = true;
  114. }
  115. }
  116. }