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
|
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader;
using System;
namespace Ryujinx.Graphics.OpenGL
{
class ComputePipeline : IComputePipeline
{
private Renderer _renderer;
private Program _program;
public ComputePipeline(Renderer renderer)
{
_renderer = renderer;
}
public void Dispatch(int groupsX, int groupsY, int groupsZ)
{
BindProgram();
GL.DispatchCompute(groupsX, groupsY, groupsZ);
UnbindProgram();
}
public void SetProgram(IProgram program)
{
_program = (Program)program;
}
public void SetStorageBuffer(int index, BufferRange buffer)
{
BindProgram();
BindBuffer(index, buffer, isStorage: true);
UnbindProgram();
}
public void SetUniformBuffer(int index, BufferRange buffer)
{
BindProgram();
BindBuffer(index, buffer, isStorage: false);
UnbindProgram();
}
private void BindBuffer(int index, BufferRange buffer, bool isStorage)
{
int bindingPoint = isStorage
? _program.GetStorageBufferBindingPoint(ShaderStage.Compute, index)
: _program.GetUniformBufferBindingPoint(ShaderStage.Compute, index);
if (bindingPoint == -1)
{
return;
}
BufferRangeTarget target = isStorage
? BufferRangeTarget.ShaderStorageBuffer
: BufferRangeTarget.UniformBuffer;
if (buffer.Buffer == null)
{
GL.BindBufferRange(target, bindingPoint, 0, IntPtr.Zero, 0);
return;
}
int bufferHandle = ((Buffer)buffer.Buffer).Handle;
IntPtr bufferOffset = (IntPtr)buffer.Offset;
GL.BindBufferRange(
target,
bindingPoint,
bufferHandle,
bufferOffset,
buffer.Size);
}
private void BindProgram()
{
_program.Bind();
}
private void UnbindProgram()
{
((GraphicsPipeline)_renderer.GraphicsPipeline).RebindProgram();
}
}
}
|