Implement transform feedback emulation for hardware without native support (#5080)

* Implement transform feedback emulation for hardware without native support

* Stop doing some useless buffer updates and account for non-zero base instance

* Reduce redundant updates even more

* Update descriptor init logic to account for ResourceLayout

* Fix transform feedback and storage buffers not being updated in some cases

* Shader cache version bump

* PR feedback

* SetInstancedDrawVertexCount must be always called after UpdateState

* Minor typo
This commit is contained in:
gdkchan 2023-06-10 18:31:38 -03:00 committed by GitHub
parent 0e95a8271a
commit eb0bb36bbf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 375 additions and 68 deletions

View file

@ -539,6 +539,14 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
engine.UpdateState();
if (instanceCount > 1)
{
// Must be called after UpdateState as it assumes the shader state
// has already been set, and that bindings have been updated already.
_channel.BufferManager.SetInstancedDrawVertexCount(count);
}
if (indexed)
{
_context.Renderer.Pipeline.DrawIndexed(count, instanceCount, firstIndex, firstVertex, firstInstance);
@ -676,6 +684,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_channel.BufferManager.SetIndexBuffer(br, IndexType.UInt);
}
_channel.BufferManager.SetInstancedDrawVertexCount(_instancedIndexCount);
_context.Renderer.Pipeline.DrawIndexed(
_instancedIndexCount,
_instanceIndex + 1,
@ -685,6 +695,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
}
else
{
_channel.BufferManager.SetInstancedDrawVertexCount(_instancedDrawStateCount);
_context.Renderer.Pipeline.Draw(
_instancedDrawStateCount,
_instanceIndex + 1,

View file

@ -269,7 +269,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_prevFirstVertex = _state.State.FirstVertex;
}
bool tfEnable = _state.State.TfEnable;
bool tfEnable = _state.State.TfEnable && _context.Capabilities.SupportsTransformFeedback;
if (!tfEnable && _prevTfEnable)
{
@ -1367,6 +1367,22 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_vsUsesDrawParameters = gs.Shaders[1]?.Info.UsesDrawParameters ?? false;
_vsClipDistancesWritten = gs.Shaders[1]?.Info.ClipDistancesWritten ?? 0;
bool hasTransformFeedback = gs.SpecializationState.TransformFeedbackDescriptors != null;
if (hasTransformFeedback != _channel.BufferManager.HasTransformFeedbackOutputs)
{
if (!_context.Capabilities.SupportsTransformFeedback)
{
// If host does not support transform feedback, and the shader changed,
// we might need to update bindings as transform feedback emulation
// uses storage buffer bindings that might have been used for something
// else in a previous draw.
_channel.BufferManager.ForceTransformFeedbackAndStorageBuffersDirty();
}
_channel.BufferManager.HasTransformFeedbackOutputs = hasTransformFeedback;
}
if (oldVsClipDistancesWritten != _vsClipDistancesWritten)
{
UpdateUserClipState();