| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- using Ryujinx.Graphics.GAL;
- using Ryujinx.Graphics.Gpu.Image;
- using Ryujinx.Graphics.Gpu.State;
- namespace Ryujinx.Graphics.Gpu.Engine
- {
- partial class Methods
- {
- private bool _drawIndexed;
- private bool _instancedDrawPending;
- private bool _instancedIndexed;
- private int _instancedFirstIndex;
- private int _instancedFirstVertex;
- private int _instancedFirstInstance;
- private int _instancedIndexCount;
- private int _instancedDrawStateFirst;
- private int _instancedDrawStateCount;
- private int _instanceIndex;
- private IbStreamer _ibStreamer;
- /// <summary>
- /// Primitive topology of the current draw.
- /// </summary>
- public PrimitiveTopology Topology { get; private set; }
- /// <summary>
- /// Finishes the draw call.
- /// This draws geometry on the bound buffers based on the current GPU state.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- private void DrawEnd(GpuState state, int argument)
- {
- var indexBuffer = state.Get<IndexBufferState>(MethodOffset.IndexBufferState);
- DrawEnd(state, indexBuffer.First, indexBuffer.Count);
- }
- /// <summary>
- /// Finishes the draw call.
- /// This draws geometry on the bound buffers based on the current GPU state.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="firstIndex">Index of the first index buffer element used on the draw</param>
- /// <param name="indexCount">Number of index buffer elements used on the draw</param>
- private void DrawEnd(GpuState state, int firstIndex, int indexCount)
- {
- ConditionalRenderEnabled renderEnable = GetRenderEnable(state);
- if (renderEnable == ConditionalRenderEnabled.False || _instancedDrawPending)
- {
- if (renderEnable == ConditionalRenderEnabled.False)
- {
- PerformDeferredDraws();
- }
- _drawIndexed = false;
- if (renderEnable == ConditionalRenderEnabled.Host)
- {
- _context.Renderer.Pipeline.EndHostConditionalRendering();
- }
- return;
- }
- UpdateState(state, firstIndex, indexCount);
- bool instanced = _vsUsesInstanceId || _isAnyVbInstanced;
- if (instanced)
- {
- _instancedDrawPending = true;
- _instancedIndexed = _drawIndexed;
- _instancedFirstIndex = firstIndex;
- _instancedFirstVertex = state.Get<int>(MethodOffset.FirstVertex);
- _instancedFirstInstance = state.Get<int>(MethodOffset.FirstInstance);
- _instancedIndexCount = indexCount;
- var drawState = state.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
- _instancedDrawStateFirst = drawState.First;
- _instancedDrawStateCount = drawState.Count;
- _drawIndexed = false;
- if (renderEnable == ConditionalRenderEnabled.Host)
- {
- _context.Renderer.Pipeline.EndHostConditionalRendering();
- }
- return;
- }
- int firstInstance = state.Get<int>(MethodOffset.FirstInstance);
- int inlineIndexCount = _ibStreamer.GetAndResetInlineIndexCount();
- if (inlineIndexCount != 0)
- {
- int firstVertex = state.Get<int>(MethodOffset.FirstVertex);
- BufferRange br = new BufferRange(_ibStreamer.GetInlineIndexBuffer(), 0, inlineIndexCount * 4);
- state.Channel.BufferManager.SetIndexBuffer(br, IndexType.UInt);
- _context.Renderer.Pipeline.DrawIndexed(
- inlineIndexCount,
- 1,
- firstIndex,
- firstVertex,
- firstInstance);
- }
- else if (_drawIndexed)
- {
- int firstVertex = state.Get<int>(MethodOffset.FirstVertex);
- _context.Renderer.Pipeline.DrawIndexed(
- indexCount,
- 1,
- firstIndex,
- firstVertex,
- firstInstance);
- }
- else
- {
- var drawState = state.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
- _context.Renderer.Pipeline.Draw(
- drawState.Count,
- 1,
- drawState.First,
- firstInstance);
- }
- _drawIndexed = false;
- if (renderEnable == ConditionalRenderEnabled.Host)
- {
- _context.Renderer.Pipeline.EndHostConditionalRendering();
- }
- }
- /// <summary>
- /// Starts draw.
- /// This sets primitive type and instanced draw parameters.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- private void DrawBegin(GpuState state, int argument)
- {
- bool incrementInstance = (argument & (1 << 26)) != 0;
- bool resetInstance = (argument & (1 << 27)) == 0;
- PrimitiveType type = (PrimitiveType)(argument & 0xffff);
- PrimitiveTypeOverride typeOverride = state.Get<PrimitiveTypeOverride>(MethodOffset.PrimitiveTypeOverride);
- if (typeOverride != PrimitiveTypeOverride.Invalid)
- {
- DrawBegin(incrementInstance, resetInstance, typeOverride.Convert());
- }
- else
- {
- DrawBegin(incrementInstance, resetInstance, type.Convert());
- }
- }
- /// <summary>
- /// Starts draw.
- /// This sets primitive type and instanced draw parameters.
- /// </summary>
- /// <param name="incrementInstance">Indicates if the current instance should be incremented</param>
- /// <param name="resetInstance">Indicates if the current instance should be set to zero</param>
- /// <param name="topology">Primitive topology</param>
- private void DrawBegin(bool incrementInstance, bool resetInstance, PrimitiveTopology topology)
- {
- if (incrementInstance)
- {
- _instanceIndex++;
- }
- else if (resetInstance)
- {
- PerformDeferredDraws();
- _instanceIndex = 0;
- }
- _context.Renderer.Pipeline.SetPrimitiveTopology(topology);
- Topology = topology;
- }
- /// <summary>
- /// Sets the index buffer count.
- /// This also sets internal state that indicates that the next draw is an indexed draw.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- private void SetIndexBufferCount(GpuState state, int argument)
- {
- _drawIndexed = true;
- }
- /// <summary>
- /// Performs a indexed draw with a low number of index buffer elements.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- private void DrawIndexedSmall(GpuState state, int argument)
- {
- DrawIndexedSmall(state, argument, false);
- }
- /// <summary>
- /// Performs a indexed draw with a low number of index buffer elements.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- private void DrawIndexedSmall2(GpuState state, int argument)
- {
- DrawIndexedSmall(state, argument);
- }
- /// <summary>
- /// Performs a indexed draw with a low number of index buffer elements,
- /// while also pre-incrementing the current instance value.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- private void DrawIndexedSmallIncInstance(GpuState state, int argument)
- {
- DrawIndexedSmall(state, argument, true);
- }
- /// <summary>
- /// Performs a indexed draw with a low number of index buffer elements,
- /// while also pre-incrementing the current instance value.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- private void DrawIndexedSmallIncInstance2(GpuState state, int argument)
- {
- DrawIndexedSmallIncInstance(state, argument);
- }
- /// <summary>
- /// Performs a indexed draw with a low number of index buffer elements,
- /// while optionally also pre-incrementing the current instance value.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- /// <param name="instanced">True to increment the current instance value, false otherwise</param>
- private void DrawIndexedSmall(GpuState state, int argument, bool instanced)
- {
- PrimitiveTypeOverride typeOverride = state.Get<PrimitiveTypeOverride>(MethodOffset.PrimitiveTypeOverride);
- DrawBegin(instanced, !instanced, typeOverride.Convert());
- int firstIndex = argument & 0xffff;
- int indexCount = (argument >> 16) & 0xfff;
- bool oldDrawIndexed = _drawIndexed;
- _drawIndexed = true;
- DrawEnd(state, firstIndex, indexCount);
- _drawIndexed = oldDrawIndexed;
- }
- /// <summary>
- /// Pushes four 8-bit index buffer elements.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- private void VbElementU8(GpuState state, int argument)
- {
- _ibStreamer.VbElementU8(_context.Renderer, argument);
- }
- /// <summary>
- /// Pushes two 16-bit index buffer elements.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- private void VbElementU16(GpuState state, int argument)
- {
- _ibStreamer.VbElementU16(_context.Renderer, argument);
- }
- /// <summary>
- /// Pushes one 32-bit index buffer element.
- /// </summary>
- /// <param name="state">Current GPU state</param>
- /// <param name="argument">Method call argument</param>
- private void VbElementU32(GpuState state, int argument)
- {
- _ibStreamer.VbElementU32(_context.Renderer, argument);
- }
- /// <summary>
- /// Perform any deferred draws.
- /// This is used for instanced draws.
- /// Since each instance is a separate draw, we defer the draw and accumulate the instance count.
- /// Once we detect the last instanced draw, then we perform the host instanced draw,
- /// with the accumulated instance count.
- /// </summary>
- public void PerformDeferredDraws()
- {
- // Perform any pending instanced draw.
- if (_instancedDrawPending)
- {
- _instancedDrawPending = false;
- if (_instancedIndexed)
- {
- _context.Renderer.Pipeline.DrawIndexed(
- _instancedIndexCount,
- _instanceIndex + 1,
- _instancedFirstIndex,
- _instancedFirstVertex,
- _instancedFirstInstance);
- }
- else
- {
- _context.Renderer.Pipeline.Draw(
- _instancedDrawStateCount,
- _instanceIndex + 1,
- _instancedDrawStateFirst,
- _instancedFirstInstance);
- }
- }
- }
- }
- }
|