Initial support for image stores, support texture sample on compute

This commit is contained in:
gdk 2019-10-17 23:41:18 -03:00 committed by Thog
parent 717ace6f6e
commit 1b7d955195
44 changed files with 1053 additions and 497 deletions

View file

@ -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();
}
}
}

View file

@ -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)

View file

@ -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()

View file

@ -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();