Initial support for image stores, support texture sample on compute
This commit is contained in:
@ -1,95 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,12 +4,13 @@ using Ryujinx.Graphics.GAL.Blend;
|
||||
using Ryujinx.Graphics.GAL.Color;
|
||||
using Ryujinx.Graphics.GAL.DepthStencil;
|
||||
using Ryujinx.Graphics.GAL.InputAssembler;
|
||||
using Ryujinx.Graphics.OpenGL.Formats;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.OpenGL
|
||||
{
|
||||
class GraphicsPipeline : IGraphicsPipeline
|
||||
class Pipeline : IPipeline
|
||||
{
|
||||
private Program _program;
|
||||
|
||||
@ -33,7 +34,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
|
||||
private uint[] _componentMasks;
|
||||
|
||||
internal GraphicsPipeline()
|
||||
internal Pipeline()
|
||||
{
|
||||
_clipOrigin = ClipOrigin.LowerLeft;
|
||||
}
|
||||
@ -62,6 +63,29 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
GL.Enable(IndexedEnableCap.Blend, index);
|
||||
}
|
||||
|
||||
public void BindImage(int index, ShaderStage stage, ITexture texture)
|
||||
{
|
||||
int unit = _program.GetImageUnit(stage, index);
|
||||
|
||||
if (unit != -1 && texture != null)
|
||||
{
|
||||
TextureView view = (TextureView)texture;
|
||||
|
||||
FormatInfo formatInfo = FormatTable.GetFormatInfo(view.Format);
|
||||
|
||||
SizedInternalFormat format = (SizedInternalFormat)formatInfo.PixelInternalFormat;
|
||||
|
||||
GL.BindImageTexture(
|
||||
unit,
|
||||
view.Handle,
|
||||
0,
|
||||
true,
|
||||
0,
|
||||
TextureAccess.ReadWrite,
|
||||
format);
|
||||
}
|
||||
}
|
||||
|
||||
public void BindIndexBuffer(BufferRange buffer, IndexType type)
|
||||
{
|
||||
_elementsType = type.Convert();
|
||||
@ -107,53 +131,48 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
}
|
||||
}
|
||||
|
||||
public void BindStorageBuffers(int index, ShaderStage stage, BufferRange[] buffers)
|
||||
public void BindStorageBuffer(int index, ShaderStage stage, BufferRange buffer)
|
||||
{
|
||||
BindBuffers(index, stage, buffers, isStorage: true);
|
||||
BindBuffer(index, stage, buffer, isStorage: true);
|
||||
}
|
||||
|
||||
public void BindUniformBuffers(int index, ShaderStage stage, BufferRange[] buffers)
|
||||
public void BindUniformBuffer(int index, ShaderStage stage, BufferRange buffer)
|
||||
{
|
||||
BindBuffers(index, stage, buffers, isStorage: false);
|
||||
BindBuffer(index, stage, buffer, isStorage: false);
|
||||
}
|
||||
|
||||
private void BindBuffers(int index, ShaderStage stage, BufferRange[] buffers, bool isStorage)
|
||||
private void BindBuffer(int index, ShaderStage stage, BufferRange buffer, bool isStorage)
|
||||
{
|
||||
for (int bufferIndex = 0; bufferIndex < buffers.Length; bufferIndex++, index++)
|
||||
int bindingPoint = isStorage
|
||||
? _program.GetStorageBufferBindingPoint(stage, index)
|
||||
: _program.GetUniformBufferBindingPoint(stage, index);
|
||||
|
||||
if (bindingPoint == -1)
|
||||
{
|
||||
int bindingPoint = isStorage
|
||||
? _program.GetStorageBufferBindingPoint(stage, index)
|
||||
: _program.GetUniformBufferBindingPoint(stage, index);
|
||||
|
||||
if (bindingPoint == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BufferRange buffer = buffers[bufferIndex];
|
||||
|
||||
BufferRangeTarget target = isStorage
|
||||
? BufferRangeTarget.ShaderStorageBuffer
|
||||
: BufferRangeTarget.UniformBuffer;
|
||||
|
||||
if (buffer.Buffer == null)
|
||||
{
|
||||
GL.BindBufferRange(target, bindingPoint, 0, IntPtr.Zero, 0);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int bufferHandle = ((Buffer)buffer.Buffer).Handle;
|
||||
|
||||
IntPtr bufferOffset = (IntPtr)buffer.Offset;
|
||||
|
||||
GL.BindBufferRange(
|
||||
target,
|
||||
bindingPoint,
|
||||
bufferHandle,
|
||||
bufferOffset,
|
||||
buffer.Size);
|
||||
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);
|
||||
}
|
||||
|
||||
public void BindVertexAttribs(VertexAttribDescriptor[] vertexAttribs)
|
||||
@ -264,6 +283,11 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispatch(int groupsX, int groupsY, int groupsZ)
|
||||
{
|
||||
GL.DispatchCompute(groupsX, groupsY, groupsZ);
|
||||
}
|
||||
|
||||
public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
|
||||
{
|
||||
if (!_program.IsLinked)
|
||||
@ -803,6 +827,16 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
SetOrigin(flipY ? ClipOrigin.UpperLeft : ClipOrigin.LowerLeft);
|
||||
}
|
||||
|
||||
public void TextureBarrier()
|
||||
{
|
||||
GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit);
|
||||
}
|
||||
|
||||
public void TextureBarrierTiled()
|
||||
{
|
||||
GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit);
|
||||
}
|
||||
|
||||
private void SetOrigin(ClipOrigin origin)
|
||||
{
|
||||
if (_clipOrigin != origin)
|
@ -6,8 +6,17 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
{
|
||||
class Program : IProgram
|
||||
{
|
||||
private const int StageShift = 5;
|
||||
private const int SbStageShift = 4;
|
||||
private const int ShaderStages = 6;
|
||||
|
||||
private const int UbStageShift = 5;
|
||||
private const int SbStageShift = 4;
|
||||
private const int TexStageShift = 5;
|
||||
private const int ImgStageShift = 3;
|
||||
|
||||
private const int UbsPerStage = 1 << UbStageShift;
|
||||
private const int SbsPerStage = 1 << SbStageShift;
|
||||
private const int TexsPerStage = 1 << TexStageShift;
|
||||
private const int ImgsPerStage = 1 << ImgStageShift;
|
||||
|
||||
public int Handle { get; private set; }
|
||||
|
||||
@ -16,12 +25,14 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
private int[] _ubBindingPoints;
|
||||
private int[] _sbBindingPoints;
|
||||
private int[] _textureUnits;
|
||||
private int[] _imageUnits;
|
||||
|
||||
public Program(IShader[] shaders)
|
||||
{
|
||||
_ubBindingPoints = new int[32 * 6];
|
||||
_sbBindingPoints = new int[16 * 6];
|
||||
_textureUnits = new int[32 * 6];
|
||||
_ubBindingPoints = new int[UbsPerStage * ShaderStages];
|
||||
_sbBindingPoints = new int[SbsPerStage * ShaderStages];
|
||||
_textureUnits = new int[TexsPerStage * ShaderStages];
|
||||
_imageUnits = new int[ImgsPerStage * ShaderStages];
|
||||
|
||||
for (int index = 0; index < _ubBindingPoints.Length; index++)
|
||||
{
|
||||
@ -38,6 +49,11 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
_textureUnits[index] = -1;
|
||||
}
|
||||
|
||||
for (int index = 0; index < _imageUnits.Length; index++)
|
||||
{
|
||||
_imageUnits[index] = -1;
|
||||
}
|
||||
|
||||
Handle = GL.CreateProgram();
|
||||
|
||||
for (int index = 0; index < shaders.Length; index++)
|
||||
@ -79,7 +95,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
|
||||
GL.UniformBlockBinding(Handle, location, ubBindingPoint);
|
||||
|
||||
int bpIndex = (int)shader.Stage << StageShift | descriptor.Slot;
|
||||
int bpIndex = (int)shader.Stage << UbStageShift | descriptor.Slot;
|
||||
|
||||
_ubBindingPoints[bpIndex] = ubBindingPoint;
|
||||
|
||||
@ -117,7 +133,27 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
|
||||
GL.Uniform1(location, textureUnit);
|
||||
|
||||
int uIndex = (int)shader.Stage << StageShift | samplerIndex++;
|
||||
int uIndex = (int)shader.Stage << TexStageShift | samplerIndex++;
|
||||
|
||||
_textureUnits[uIndex] = textureUnit;
|
||||
|
||||
textureUnit++;
|
||||
}
|
||||
|
||||
int imageIndex = 0;
|
||||
|
||||
foreach (TextureDescriptor descriptor in shader.Info.Images)
|
||||
{
|
||||
int location = GL.GetUniformLocation(Handle, descriptor.Name);
|
||||
|
||||
if (location < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
GL.Uniform1(location, textureUnit);
|
||||
|
||||
int uIndex = (int)shader.Stage << ImgStageShift | imageIndex++;
|
||||
|
||||
_textureUnits[uIndex] = textureUnit;
|
||||
|
||||
@ -133,7 +169,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
|
||||
public int GetUniformBufferBindingPoint(ShaderStage stage, int index)
|
||||
{
|
||||
return _ubBindingPoints[(int)stage << StageShift | index];
|
||||
return _ubBindingPoints[(int)stage << UbStageShift | index];
|
||||
}
|
||||
|
||||
public int GetStorageBufferBindingPoint(ShaderStage stage, int index)
|
||||
@ -143,7 +179,12 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
|
||||
public int GetTextureUnit(ShaderStage stage, int index)
|
||||
{
|
||||
return _textureUnits[(int)stage << StageShift | index];
|
||||
return _textureUnits[(int)stage << TexStageShift | index];
|
||||
}
|
||||
|
||||
public int GetImageUnit(ShaderStage stage, int index)
|
||||
{
|
||||
return _textureUnits[(int)stage << ImgStageShift | index];
|
||||
}
|
||||
|
||||
private void CheckProgramLink()
|
||||
|
@ -8,8 +8,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
{
|
||||
public class Renderer : IRenderer
|
||||
{
|
||||
public IComputePipeline ComputePipeline { get; }
|
||||
public IGraphicsPipeline GraphicsPipeline { get; }
|
||||
public IPipeline Pipeline { get; }
|
||||
|
||||
private Counters _counters;
|
||||
|
||||
@ -21,8 +20,7 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
|
||||
public Renderer()
|
||||
{
|
||||
ComputePipeline = new ComputePipeline(this);
|
||||
GraphicsPipeline = new GraphicsPipeline();
|
||||
Pipeline = new Pipeline();
|
||||
|
||||
_counters = new Counters();
|
||||
|
||||
|
Reference in New Issue
Block a user