Initial transform feedback support (#1370)

* Initial transform feedback support

* Some nits and fixes

* Update ReportCounterType and Write method

* Can't change shader or TFB bindings while TFB is active

* Fix geometry shader input names with new naming
This commit is contained in:
gdkchan 2020-07-15 00:01:10 -03:00 committed by GitHub
parent 16dafe6316
commit 788ca6a411
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 468 additions and 68 deletions

View file

@ -40,6 +40,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
private bool _forceShaderUpdate;
private bool _prevTfEnable;
/// <summary>
/// Creates a new instance of the GPU methods class.
/// </summary>
@ -124,6 +126,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// <param name="state">Guest GPU state</param>
private void UpdateState(GpuState state)
{
bool tfEnable = state.Get<Boolean32>(MethodOffset.TfEnable);
if (!tfEnable && _prevTfEnable)
{
_context.Renderer.Pipeline.EndTransformFeedback();
_prevTfEnable = false;
}
// Shaders must be the first one to be updated if modified, because
// some of the other state depends on information from the currently
// bound shaders.
@ -134,6 +144,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
UpdateShaderState(state);
}
if (state.QueryModified(MethodOffset.TfBufferState))
{
UpdateTfBufferState(state);
}
if (state.QueryModified(MethodOffset.ClipDistanceEnable))
{
UpdateUserClipState(state);
@ -258,6 +273,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
}
CommitBindings();
if (tfEnable && !_prevTfEnable)
{
_context.Renderer.Pipeline.BeginTransformFeedback(PrimitiveType.Convert());
_prevTfEnable = true;
}
}
/// <summary>
@ -318,7 +339,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// </summary>
/// <param name="state">Current GPU state</param>
/// <param name="useControl">Use draw buffers information from render target control register</param>
/// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
/// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
private void UpdateRenderTargetState(GpuState state, bool useControl, int singleUse = -1)
{
var rtControl = state.Get<RtControl>(MethodOffset.RtControl);
@ -1003,6 +1024,27 @@ namespace Ryujinx.Graphics.Gpu.Engine
_context.Renderer.Pipeline.SetProgram(gs.HostProgram);
}
/// <summary>
/// Updates transform feedback buffer state based on the guest GPU state.
/// </summary>
/// <param name="state">Current GPU state</param>
private void UpdateTfBufferState(GpuState state)
{
for (int index = 0; index < Constants.TotalTransformFeedbackBuffers; index++)
{
TfBufferState tfb = state.Get<TfBufferState>(MethodOffset.TfBufferState, index);
if (!tfb.Enable)
{
BufferManager.SetTransformFeedbackBuffer(index, 0, 0);
continue;
}
BufferManager.SetTransformFeedbackBuffer(index, tfb.Address.Pack(), (uint)tfb.Size);
}
}
/// <summary>
/// Updates user-defined clipping based on the guest GPU state.
/// </summary>