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:
parent
17550a21cd
commit
deb3c58020
5 changed files with 128 additions and 23 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue