MethodDraw.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. using Ryujinx.Graphics.Gpu.State;
  2. using Ryujinx.Graphics.Gpu.Image;
  3. namespace Ryujinx.Graphics.Gpu.Engine
  4. {
  5. partial class Methods
  6. {
  7. private bool _drawIndexed;
  8. private int _firstIndex;
  9. private int _indexCount;
  10. private bool _instancedDrawPending;
  11. private bool _instancedIndexed;
  12. private int _instancedFirstIndex;
  13. private int _instancedFirstVertex;
  14. private int _instancedFirstInstance;
  15. private int _instancedIndexCount;
  16. private int _instancedDrawStateFirst;
  17. private int _instancedDrawStateCount;
  18. private int _instanceIndex;
  19. /// <summary>
  20. /// Primitive type of the current draw.
  21. /// </summary>
  22. public PrimitiveType PrimitiveType { get; private set; }
  23. /// <summary>
  24. /// Finishes draw call.
  25. /// This draws geometry on the bound buffers based on the current GPU state.
  26. /// </summary>
  27. /// <param name="state">Current GPU state</param>
  28. /// <param name="argument">Method call argument</param>
  29. private void DrawEnd(GpuState state, int argument)
  30. {
  31. ConditionalRenderEnabled renderEnable = GetRenderEnable(state);
  32. if (renderEnable == ConditionalRenderEnabled.False || _instancedDrawPending)
  33. {
  34. if (renderEnable == ConditionalRenderEnabled.False)
  35. {
  36. PerformDeferredDraws();
  37. }
  38. _drawIndexed = false;
  39. if (renderEnable == ConditionalRenderEnabled.Host)
  40. {
  41. _context.Renderer.Pipeline.EndHostConditionalRendering();
  42. }
  43. return;
  44. }
  45. UpdateState(state);
  46. bool instanced = _vsUsesInstanceId || _isAnyVbInstanced;
  47. if (instanced)
  48. {
  49. _instancedDrawPending = true;
  50. _instancedIndexed = _drawIndexed;
  51. _instancedFirstIndex = _firstIndex;
  52. _instancedFirstVertex = state.Get<int>(MethodOffset.FirstVertex);
  53. _instancedFirstInstance = state.Get<int>(MethodOffset.FirstInstance);
  54. _instancedIndexCount = _indexCount;
  55. var drawState = state.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
  56. _instancedDrawStateFirst = drawState.First;
  57. _instancedDrawStateCount = drawState.Count;
  58. _drawIndexed = false;
  59. if (renderEnable == ConditionalRenderEnabled.Host)
  60. {
  61. _context.Renderer.Pipeline.EndHostConditionalRendering();
  62. }
  63. return;
  64. }
  65. int firstInstance = state.Get<int>(MethodOffset.FirstInstance);
  66. if (_drawIndexed)
  67. {
  68. _drawIndexed = false;
  69. int firstVertex = state.Get<int>(MethodOffset.FirstVertex);
  70. _context.Renderer.Pipeline.DrawIndexed(
  71. _indexCount,
  72. 1,
  73. _firstIndex,
  74. firstVertex,
  75. firstInstance);
  76. }
  77. else
  78. {
  79. var drawState = state.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
  80. _context.Renderer.Pipeline.Draw(
  81. drawState.Count,
  82. 1,
  83. drawState.First,
  84. firstInstance);
  85. }
  86. if (renderEnable == ConditionalRenderEnabled.Host)
  87. {
  88. _context.Renderer.Pipeline.EndHostConditionalRendering();
  89. }
  90. }
  91. /// <summary>
  92. /// Starts draw.
  93. /// This sets primitive type and instanced draw parameters.
  94. /// </summary>
  95. /// <param name="state">Current GPU state</param>
  96. /// <param name="argument">Method call argument</param>
  97. private void DrawBegin(GpuState state, int argument)
  98. {
  99. if ((argument & (1 << 26)) != 0)
  100. {
  101. _instanceIndex++;
  102. }
  103. else if ((argument & (1 << 27)) == 0)
  104. {
  105. PerformDeferredDraws();
  106. _instanceIndex = 0;
  107. }
  108. PrimitiveType type = (PrimitiveType)(argument & 0xffff);
  109. _context.Renderer.Pipeline.SetPrimitiveTopology(type.Convert());
  110. PrimitiveType = type;
  111. }
  112. /// <summary>
  113. /// Sets the index buffer count.
  114. /// This also sets internal state that indicates that the next draw is an indexed draw.
  115. /// </summary>
  116. /// <param name="state">Current GPU state</param>
  117. /// <param name="argument">Method call argument</param>
  118. private void SetIndexBufferCount(GpuState state, int argument)
  119. {
  120. _drawIndexed = true;
  121. }
  122. /// <summary>
  123. /// Perform any deferred draws.
  124. /// This is used for instanced draws.
  125. /// Since each instance is a separate draw, we defer the draw and accumulate the instance count.
  126. /// Once we detect the last instanced draw, then we perform the host instanced draw,
  127. /// with the accumulated instance count.
  128. /// </summary>
  129. public void PerformDeferredDraws()
  130. {
  131. // Perform any pending instanced draw.
  132. if (_instancedDrawPending)
  133. {
  134. _instancedDrawPending = false;
  135. if (_instancedIndexed)
  136. {
  137. _context.Renderer.Pipeline.DrawIndexed(
  138. _instancedIndexCount,
  139. _instanceIndex + 1,
  140. _instancedFirstIndex,
  141. _instancedFirstVertex,
  142. _instancedFirstInstance);
  143. }
  144. else
  145. {
  146. _context.Renderer.Pipeline.Draw(
  147. _instancedDrawStateCount,
  148. _instanceIndex + 1,
  149. _instancedDrawStateFirst,
  150. _instancedFirstInstance);
  151. }
  152. }
  153. }
  154. }
  155. }