aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-06-10 18:31:38 -0300
committerGitHub <noreply@github.com>2023-06-10 18:31:38 -0300
commiteb0bb36bbfc3a4f5f2ac1c8721e192239f899a1d (patch)
treee43650855d28e8d49d7ad2d82466647263c3fe16 /src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
parent0e95a8271ac96b2c54907858140e2511a25a2b10 (diff)
Implement transform feedback emulation for hardware without native support (#5080)1.1.882
* 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
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs')
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
index 6ca74a37..87e5457f 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
@@ -234,6 +234,45 @@ namespace Ryujinx.Graphics.Shader.Translation
public void PrepareForVertexReturn()
{
+ if (!Config.GpuAccessor.QueryHostSupportsTransformFeedback() && Config.GpuAccessor.QueryTransformFeedbackEnabled())
+ {
+ Operand vertexCount = this.Load(StorageKind.StorageBuffer, Constants.TfeInfoBinding, Const(1));
+
+ for (int tfbIndex = 0; tfbIndex < Constants.TfeBuffersCount; tfbIndex++)
+ {
+ var locations = Config.GpuAccessor.QueryTransformFeedbackVaryingLocations(tfbIndex);
+ var stride = Config.GpuAccessor.QueryTransformFeedbackStride(tfbIndex);
+
+ Operand baseOffset = this.Load(StorageKind.StorageBuffer, Constants.TfeInfoBinding, Const(0), Const(tfbIndex));
+ Operand baseVertex = this.Load(StorageKind.Input, IoVariable.BaseVertex);
+ Operand baseInstance = this.Load(StorageKind.Input, IoVariable.BaseInstance);
+ Operand vertexIndex = this.Load(StorageKind.Input, IoVariable.VertexIndex);
+ Operand instanceIndex = this.Load(StorageKind.Input, IoVariable.InstanceIndex);
+
+ Operand outputVertexOffset = this.ISubtract(vertexIndex, baseVertex);
+ Operand outputInstanceOffset = this.ISubtract(instanceIndex, baseInstance);
+
+ Operand outputBaseVertex = this.IMultiply(outputInstanceOffset, vertexCount);
+
+ Operand vertexOffset = this.IMultiply(this.IAdd(outputBaseVertex, outputVertexOffset), Const(stride / 4));
+ baseOffset = this.IAdd(baseOffset, vertexOffset);
+
+ for (int j = 0; j < locations.Length; j++)
+ {
+ byte location = locations[j];
+ if (location == 0xff)
+ {
+ continue;
+ }
+
+ Operand offset = this.IAdd(baseOffset, Const(j));
+ Operand value = Instructions.AttributeMap.GenerateAttributeLoad(this, null, location * 4, isOutput: true, isPerPatch: false);
+
+ this.Store(StorageKind.StorageBuffer, Constants.TfeBufferBaseBinding + tfbIndex, Const(0), offset, value);
+ }
+ }
+ }
+
if (Config.GpuAccessor.QueryViewportTransformDisable())
{
Operand x = this.Load(StorageKind.Output, IoVariable.Position, null, Const(0));