Support 2D array copy operation in the 2D engine

This make every copy right in the GPU side.
Thie CPU copy probably needs to be updated
This commit is contained in:
Thog 2018-12-24 15:21:02 +01:00
parent 17550a21cd
commit deb3c58020
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
5 changed files with 128 additions and 23 deletions

View file

@ -25,16 +25,20 @@ namespace Ryujinx.Graphics.Gal
void Render();
void Copy(
long SrcKey,
long DstKey,
int SrcX0,
int SrcY0,
int SrcX1,
int SrcY1,
int DstX0,
int DstY0,
int DstX1,
int DstY1);
GalImage SrcImage,
GalImage DstImage,
long SrcKey,
long DstKey,
int SrcLayer,
int DstLayer,
int SrcX0,
int SrcY0,
int SrcX1,
int SrcY1,
int DstX0,
int DstY0,
int DstX1,
int DstY1);
void Reinterpret(long Key, GalImage NewImage);
}

View file

@ -389,16 +389,20 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
public void Copy(
long SrcKey,
long DstKey,
int SrcX0,
int SrcY0,
int SrcX1,
int SrcY1,
int DstX0,
int DstY0,
int DstX1,
int DstY1)
GalImage SrcImage,
GalImage DstImage,
long SrcKey,
long DstKey,
int SrcLayer,
int DstLayer,
int SrcX0,
int SrcY0,
int SrcX1,
int SrcY1,
int DstX0,
int DstY0,
int DstX1,
int DstY1)
{
if (Texture.TryGetImageHandler(SrcKey, out ImageHandler SrcTex) &&
Texture.TryGetImageHandler(DstKey, out ImageHandler DstTex))
@ -425,8 +429,24 @@ namespace Ryujinx.Graphics.Gal.OpenGL
FramebufferAttachment Attachment = GetAttachment(SrcTex);
GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, Attachment, SrcTex.Handle, 0);
GL.FramebufferTexture(FramebufferTarget.DrawFramebuffer, Attachment, DstTex.Handle, 0);
if (ImageUtils.IsArray(SrcImage.TextureTarget) && SrcLayer > 0)
{
GL.FramebufferTextureLayer(FramebufferTarget.ReadFramebuffer, Attachment, SrcTex.Handle, 0, SrcLayer);
}
else
{
GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, Attachment, SrcTex.Handle, 0);
}
if (ImageUtils.IsArray(DstImage.TextureTarget) && DstLayer > 0)
{
GL.FramebufferTextureLayer(FramebufferTarget.DrawFramebuffer, Attachment, DstTex.Handle, 0, DstLayer);
}
else
{
GL.FramebufferTexture(FramebufferTarget.DrawFramebuffer, Attachment, DstTex.Handle, 0);
}
BlitFramebufferFilter Filter = BlitFramebufferFilter.Nearest;

View file

@ -1,6 +1,7 @@
using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Memory;
using Ryujinx.Graphics.Texture;
using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics
@ -11,6 +12,7 @@ namespace Ryujinx.Graphics
{
None,
Texture,
TextureMirror,
ColorBuffer,
ZetaBuffer
}
@ -20,6 +22,7 @@ namespace Ryujinx.Graphics
private HashSet<long>[] UploadedKeys;
private Dictionary<long, ImageType> ImageTypes;
private Dictionary<long, int> MirroredTextures;
public GpuResourceManager(NvGpu Gpu)
{
@ -33,6 +36,7 @@ namespace Ryujinx.Graphics
}
ImageTypes = new Dictionary<long, ImageType>();
MirroredTextures = new Dictionary<long, int>();
}
public void SendColorBuffer(NvGpuVmm Vmm, long Position, int Attachment, GalImage NewImage)
@ -70,6 +74,30 @@ namespace Ryujinx.Graphics
ImageTypes[Position] = ImageType.Texture;
}
public bool TryGetTextureMirorLayer(long Position, out int Layer)
{
if (MirroredTextures.TryGetValue(Position, out Layer))
{
ImageType Type = ImageTypes[Position];
if (Type != ImageType.Texture && Type != ImageType.TextureMirror)
{
throw new InvalidOperationException();
}
return true;
}
Layer = -1;
return false;
}
public void SetTextureMirror(long Position, int Layer)
{
ImageTypes[Position] = ImageType.TextureMirror;
MirroredTextures[Position] = Layer;
}
private void PrepareSendTexture(NvGpuVmm Vmm, long Position, GalImage NewImage)
{
long Size = ImageUtils.GetSize(NewImage);

View file

@ -86,12 +86,16 @@ namespace Ryujinx.Graphics.Graphics3d
long SrcKey = Vmm.GetPhysicalAddress(SrcAddress);
long DstKey = Vmm.GetPhysicalAddress(DstAddress);
bool IsSrcLayered = false;
bool IsDstLayered = false;
GalTextureTarget SrcTarget = GalTextureTarget.TwoD;
if (SrcDepth != 0)
{
SrcTarget = GalTextureTarget.TwoDArray;
SrcDepth++;
IsSrcLayered = true;
}
else
{
@ -104,6 +108,7 @@ namespace Ryujinx.Graphics.Graphics3d
{
DstTarget = GalTextureTarget.TwoDArray;
DstDepth++;
IsDstLayered = true;
}
else
{
@ -131,19 +136,63 @@ namespace Ryujinx.Graphics.Graphics3d
SrcTexture.Pitch = SrcPitch;
DstTexture.Pitch = DstPitch;
long GetLayerOffset(GalImage Image, int Layer)
{
// FIXME: CALCULATE THE REAL TEXTURE SIZE (GPU SIZE NOT OGL SIZE)
// TODO: mip map
return ImageUtils.GetSize(Image) * Layer;
}
int SrcLayerIndex = -1;
if (IsSrcLayered && Gpu.ResourceManager.TryGetTextureMirorLayer(SrcKey, out SrcLayerIndex))
{
SrcKey = SrcKey - GetLayerOffset(SrcTexture, SrcLayerIndex);
}
int DstLayerIndex = -1;
if (IsDstLayered && Gpu.ResourceManager.TryGetTextureMirorLayer(DstKey, out DstLayerIndex))
{
DstKey = DstKey - GetLayerOffset(DstTexture, DstLayerIndex);
}
Gpu.ResourceManager.SendTexture(Vmm, SrcKey, SrcTexture);
Gpu.ResourceManager.SendTexture(Vmm, DstKey, DstTexture);
if (IsSrcLayered && SrcLayerIndex == -1)
{
for (int Layer = 0; Layer < SrcTexture.Depth; Layer++)
{
Gpu.ResourceManager.SetTextureMirror(SrcKey + GetLayerOffset(SrcTexture, Layer), Layer);
}
SrcLayerIndex = 0;
}
if (IsDstLayered && DstLayerIndex == -1)
{
for (int Layer = 0; Layer < DstTexture.Depth; Layer++)
{
Gpu.ResourceManager.SetTextureMirror(DstKey + GetLayerOffset(DstTexture, Layer), Layer);
}
DstLayerIndex = 0;
}
int SrcBlitX1 = (int)(SrcBlitX >> 32);
int SrcBlitY1 = (int)(SrcBlitY >> 32);
int SrcBlitX2 = (int)(SrcBlitX + DstBlitW * BlitDuDx >> 32);
int SrcBlitY2 = (int)(SrcBlitY + DstBlitH * BlitDvDy >> 32);
// TODO: support 2d array copy
Gpu.Renderer.RenderTarget.Copy(
SrcTexture,
DstTexture,
SrcKey,
DstKey,
SrcLayerIndex,
DstLayerIndex,
SrcBlitX1,
SrcBlitY1,
SrcBlitX2,
@ -157,6 +206,8 @@ namespace Ryujinx.Graphics.Graphics3d
//the texture is modified by the guest, however it doesn't
//work when resources that the gpu can write to are copied,
//like framebuffers.
// FIXME: SUPPORT MULTILAYER CORRECTLY HERE (this will cause weird stuffs on the first layer)
ImageUtils.CopyTexture(
Vmm,
SrcTexture,

View file

@ -11,6 +11,7 @@ namespace Ryujinx.Graphics.Graphics3d
DstWidth = 0x86,
DstHeight = 0x87,
DstAddress = 0x88,
DstAddressLow = 0x89,
SrcFormat = 0x8c,
SrcLinear = 0x8d,
SrcBlockDimensions = 0x8e,
@ -20,6 +21,7 @@ namespace Ryujinx.Graphics.Graphics3d
SrcWidth = 0x92,
SrcHeight = 0x93,
SrcAddress = 0x94,
SrcAddressLow = 0x95,
ClipEnable = 0xa4,
CopyOperation = 0xab,
BlitControl = 0x223,