aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsCompute.cs
blob: cbbfd251d824d0eeab80dd15c2a64c552c3daa4c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Shader;
using System;

namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
{
    /// <summary>
    /// Vertex, tessellation and geometry as compute shader draw manager.
    /// </summary>
    class VtgAsCompute : IDisposable
    {
        private readonly GpuContext _context;
        private readonly GpuChannel _channel;
        private readonly DeviceStateWithShadow<ThreedClassState> _state;
        private readonly VtgAsComputeContext _vacContext;

        /// <summary>
        /// Creates a new instance of the vertex, tessellation and geometry as compute shader draw manager.
        /// </summary>
        /// <param name="context">GPU context</param>
        /// <param name="channel">GPU channel</param>
        /// <param name="state">3D engine state</param>
        public VtgAsCompute(GpuContext context, GpuChannel channel, DeviceStateWithShadow<ThreedClassState> state)
        {
            _context = context;
            _channel = channel;
            _state = state;
            _vacContext = new(context);
        }

        /// <summary>
        /// Emulates the pre-rasterization stages of a draw operation using a compute shader.
        /// </summary>
        /// <param name="engine">3D engine</param>
        /// <param name="vertexAsCompute">Vertex shader converted to compute</param>
        /// <param name="geometryAsCompute">Optional geometry shader converted to compute</param>
        /// <param name="vertexPassthroughProgram">Fragment shader with a vertex passthrough shader to feed the compute output into the fragment stage</param>
        /// <param name="topology">Primitive topology of the draw</param>
        /// <param name="count">Index or vertex count of the draw</param>
        /// <param name="instanceCount">Instance count</param>
        /// <param name="firstIndex">First index on the index buffer, for indexed draws</param>
        /// <param name="firstVertex">First vertex on the vertex buffer</param>
        /// <param name="firstInstance">First instance</param>
        /// <param name="indexed">Whether the draw is indexed</param>
        public void DrawAsCompute(
            ThreedClass engine,
            ShaderAsCompute vertexAsCompute,
            ShaderAsCompute geometryAsCompute,
            IProgram vertexPassthroughProgram,
            PrimitiveTopology topology,
            int count,
            int instanceCount,
            int firstIndex,
            int firstVertex,
            int firstInstance,
            bool indexed)
        {
            VtgAsComputeState state = new(
                _context,
                _channel,
                _state,
                _vacContext,
                engine,
                vertexAsCompute,
                geometryAsCompute,
                vertexPassthroughProgram,
                topology,
                count,
                instanceCount,
                firstIndex,
                firstVertex,
                firstInstance,
                indexed);

            state.RunVertex();
            state.RunGeometry();
            state.RunFragment();

            _vacContext.FreeBuffers();
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _vacContext.Dispose();
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}