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
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,8 +25,12 @@ namespace Ryujinx.Graphics.Gal
void Render(); void Render();
void Copy( void Copy(
GalImage SrcImage,
GalImage DstImage,
long SrcKey, long SrcKey,
long DstKey, long DstKey,
int SrcLayer,
int DstLayer,
int SrcX0, int SrcX0,
int SrcY0, int SrcY0,
int SrcX1, int SrcX1,

View file

@ -389,8 +389,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
} }
public void Copy( public void Copy(
GalImage SrcImage,
GalImage DstImage,
long SrcKey, long SrcKey,
long DstKey, long DstKey,
int SrcLayer,
int DstLayer,
int SrcX0, int SrcX0,
int SrcY0, int SrcY0,
int SrcX1, int SrcX1,
@ -425,8 +429,24 @@ namespace Ryujinx.Graphics.Gal.OpenGL
FramebufferAttachment Attachment = GetAttachment(SrcTex); FramebufferAttachment Attachment = GetAttachment(SrcTex);
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); 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); GL.FramebufferTexture(FramebufferTarget.DrawFramebuffer, Attachment, DstTex.Handle, 0);
}
BlitFramebufferFilter Filter = BlitFramebufferFilter.Nearest; BlitFramebufferFilter Filter = BlitFramebufferFilter.Nearest;

View file

@ -1,6 +1,7 @@
using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Memory; using Ryujinx.Graphics.Memory;
using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Graphics namespace Ryujinx.Graphics
@ -11,6 +12,7 @@ namespace Ryujinx.Graphics
{ {
None, None,
Texture, Texture,
TextureMirror,
ColorBuffer, ColorBuffer,
ZetaBuffer ZetaBuffer
} }
@ -20,6 +22,7 @@ namespace Ryujinx.Graphics
private HashSet<long>[] UploadedKeys; private HashSet<long>[] UploadedKeys;
private Dictionary<long, ImageType> ImageTypes; private Dictionary<long, ImageType> ImageTypes;
private Dictionary<long, int> MirroredTextures;
public GpuResourceManager(NvGpu Gpu) public GpuResourceManager(NvGpu Gpu)
{ {
@ -33,6 +36,7 @@ namespace Ryujinx.Graphics
} }
ImageTypes = new Dictionary<long, ImageType>(); ImageTypes = new Dictionary<long, ImageType>();
MirroredTextures = new Dictionary<long, int>();
} }
public void SendColorBuffer(NvGpuVmm Vmm, long Position, int Attachment, GalImage NewImage) public void SendColorBuffer(NvGpuVmm Vmm, long Position, int Attachment, GalImage NewImage)
@ -70,6 +74,30 @@ namespace Ryujinx.Graphics
ImageTypes[Position] = ImageType.Texture; 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) private void PrepareSendTexture(NvGpuVmm Vmm, long Position, GalImage NewImage)
{ {
long Size = ImageUtils.GetSize(NewImage); long Size = ImageUtils.GetSize(NewImage);

View file

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

View file

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