Support deswizzle of sparse tiled textures and some frame buffer fixes (#275)
* Attempt to support deswizzle of sparse tiled textures * Use correct frame buffer and viewport sizes, started to clean up the copy engine * Correct texture width alignment * Use Scale/Translate registers to calculate viewport rect * Allow texture copy between frame buffers
This commit is contained in:
parent
8b685b12f0
commit
60f2198a1e
11 changed files with 237 additions and 116 deletions
|
@ -22,6 +22,25 @@ namespace Ryujinx.Graphics.Gal
|
||||||
|
|
||||||
void Render();
|
void Render();
|
||||||
|
|
||||||
|
void Copy(
|
||||||
|
long SrcKey,
|
||||||
|
long DstKey,
|
||||||
|
int SrcX0,
|
||||||
|
int SrcY0,
|
||||||
|
int SrcX1,
|
||||||
|
int SrcY1,
|
||||||
|
int DstX0,
|
||||||
|
int DstY0,
|
||||||
|
int DstX1,
|
||||||
|
int DstY1);
|
||||||
|
|
||||||
void GetBufferData(long Key, Action<byte[]> Callback);
|
void GetBufferData(long Key, Action<byte[]> Callback);
|
||||||
|
|
||||||
|
void SetBufferData(
|
||||||
|
long Key,
|
||||||
|
int Width,
|
||||||
|
int Height,
|
||||||
|
GalTextureFormat Format,
|
||||||
|
byte[] Buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -78,11 +78,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public void Create(long Key, int Width, int Height)
|
public void Create(long Key, int Width, int Height)
|
||||||
{
|
{
|
||||||
//TODO: We should either use the original frame buffer size,
|
|
||||||
//or just remove the Width/Height arguments.
|
|
||||||
Width = Window.Width;
|
|
||||||
Height = Window.Height;
|
|
||||||
|
|
||||||
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
||||||
{
|
{
|
||||||
if (Fb.Width != Width ||
|
if (Fb.Width != Width ||
|
||||||
|
@ -125,8 +120,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
||||||
|
|
||||||
GL.Viewport(0, 0, Width, Height);
|
|
||||||
|
|
||||||
Fbs.Add(Key, Fb);
|
Fbs.Add(Key, Fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +223,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
Viewport = new Rect(X, Y, Width, Height);
|
Viewport = new Rect(X, Y, Width, Height);
|
||||||
|
|
||||||
//TODO
|
SetViewport(Viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetViewport(Rect Viewport)
|
||||||
|
{
|
||||||
|
GL.Viewport(
|
||||||
|
Viewport.X,
|
||||||
|
Viewport.Y,
|
||||||
|
Viewport.Width,
|
||||||
|
Viewport.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render()
|
public void Render()
|
||||||
|
@ -300,10 +302,38 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
GL.Enable(EnableCap.Blend);
|
GL.Enable(EnableCap.Blend);
|
||||||
}
|
}
|
||||||
|
|
||||||
//GL.Viewport(0, 0, 1280, 720);
|
SetViewport(Viewport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Copy(
|
||||||
|
long SrcKey,
|
||||||
|
long DstKey,
|
||||||
|
int SrcX0,
|
||||||
|
int SrcY0,
|
||||||
|
int SrcX1,
|
||||||
|
int SrcY1,
|
||||||
|
int DstX0,
|
||||||
|
int DstY0,
|
||||||
|
int DstX1,
|
||||||
|
int DstY1)
|
||||||
|
{
|
||||||
|
if (Fbs.TryGetValue(SrcKey, out FrameBuffer SrcFb) &&
|
||||||
|
Fbs.TryGetValue(DstKey, out FrameBuffer DstFb))
|
||||||
|
{
|
||||||
|
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb.Handle);
|
||||||
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb.Handle);
|
||||||
|
|
||||||
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||||
|
|
||||||
|
GL.BlitFramebuffer(
|
||||||
|
SrcX0, SrcY0, SrcX1, SrcY1,
|
||||||
|
DstX0, DstY0, DstX1, DstY1,
|
||||||
|
ClearBufferMask.ColorBufferBit,
|
||||||
|
BlitFramebufferFilter.Linear);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void GetBufferData(long Key, Action<byte[]> Callback)
|
public void GetBufferData(long Key, Action<byte[]> Callback)
|
||||||
{
|
{
|
||||||
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
||||||
|
@ -329,13 +359,35 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetViewport(Rect Viewport)
|
public void SetBufferData(
|
||||||
|
long Key,
|
||||||
|
int Width,
|
||||||
|
int Height,
|
||||||
|
GalTextureFormat Format,
|
||||||
|
byte[] Buffer)
|
||||||
{
|
{
|
||||||
GL.Viewport(
|
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
||||||
Viewport.X,
|
{
|
||||||
Viewport.Y,
|
GL.BindTexture(TextureTarget.Texture2D, Fb.TexHandle);
|
||||||
Viewport.Width,
|
|
||||||
Viewport.Height);
|
const int Level = 0;
|
||||||
|
const int Border = 0;
|
||||||
|
|
||||||
|
const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
|
||||||
|
|
||||||
|
(PixelFormat GlFormat, PixelType Type) = OGLEnumConverter.GetTextureFormat(Format);
|
||||||
|
|
||||||
|
GL.TexImage2D(
|
||||||
|
TextureTarget.Texture2D,
|
||||||
|
Level,
|
||||||
|
InternalFmt,
|
||||||
|
Width,
|
||||||
|
Height,
|
||||||
|
Border,
|
||||||
|
GlFormat,
|
||||||
|
Type,
|
||||||
|
Buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureInitialized()
|
private void EnsureInitialized()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.Graphics.Gal;
|
using Ryujinx.Graphics.Gal;
|
||||||
using Ryujinx.HLE.Gpu.Memory;
|
using Ryujinx.HLE.Gpu.Memory;
|
||||||
using Ryujinx.HLE.Gpu.Texture;
|
using Ryujinx.HLE.Gpu.Texture;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.Gpu.Engines
|
namespace Ryujinx.HLE.Gpu.Engines
|
||||||
|
@ -64,6 +65,8 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0;
|
bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0;
|
||||||
int SrcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth);
|
int SrcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth);
|
||||||
int SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight);
|
int SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight);
|
||||||
|
int SrcPitch = ReadRegister(NvGpuEngine2dReg.SrcPitch);
|
||||||
|
int SrcBlkDim = ReadRegister(NvGpuEngine2dReg.SrcBlockDimensions);
|
||||||
|
|
||||||
bool DstLinear = ReadRegister(NvGpuEngine2dReg.DstLinear) != 0;
|
bool DstLinear = ReadRegister(NvGpuEngine2dReg.DstLinear) != 0;
|
||||||
int DstWidth = ReadRegister(NvGpuEngine2dReg.DstWidth);
|
int DstWidth = ReadRegister(NvGpuEngine2dReg.DstWidth);
|
||||||
|
@ -71,73 +74,112 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
int DstPitch = ReadRegister(NvGpuEngine2dReg.DstPitch);
|
int DstPitch = ReadRegister(NvGpuEngine2dReg.DstPitch);
|
||||||
int DstBlkDim = ReadRegister(NvGpuEngine2dReg.DstBlockDimensions);
|
int DstBlkDim = ReadRegister(NvGpuEngine2dReg.DstBlockDimensions);
|
||||||
|
|
||||||
|
TextureSwizzle SrcSwizzle = SrcLinear
|
||||||
|
? TextureSwizzle.Pitch
|
||||||
|
: TextureSwizzle.BlockLinear;
|
||||||
|
|
||||||
TextureSwizzle DstSwizzle = DstLinear
|
TextureSwizzle DstSwizzle = DstLinear
|
||||||
? TextureSwizzle.Pitch
|
? TextureSwizzle.Pitch
|
||||||
: TextureSwizzle.BlockLinear;
|
: TextureSwizzle.BlockLinear;
|
||||||
|
|
||||||
|
int SrcBlockHeight = 1 << ((SrcBlkDim >> 4) & 0xf);
|
||||||
int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);
|
int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);
|
||||||
|
|
||||||
long Key = Vmm.GetPhysicalAddress(MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress));
|
|
||||||
|
|
||||||
long SrcAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress);
|
long SrcAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress);
|
||||||
long DstAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.DstAddress);
|
long DstAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.DstAddress);
|
||||||
|
|
||||||
bool IsFbTexture = Gpu.Engine3d.IsFrameBufferPosition(Key);
|
long SrcKey = Vmm.GetPhysicalAddress(SrcAddress);
|
||||||
|
long DstKey = Vmm.GetPhysicalAddress(DstAddress);
|
||||||
|
|
||||||
if (IsFbTexture && DstLinear)
|
bool IsSrcFb = Gpu.Engine3d.IsFrameBufferPosition(SrcKey);
|
||||||
|
bool IsDstFb = Gpu.Engine3d.IsFrameBufferPosition(DstKey);
|
||||||
|
|
||||||
|
TextureInfo SrcTexture()
|
||||||
{
|
{
|
||||||
DstSwizzle = TextureSwizzle.BlockLinear;
|
return new TextureInfo(
|
||||||
|
SrcAddress,
|
||||||
|
SrcWidth,
|
||||||
|
SrcHeight,
|
||||||
|
SrcPitch,
|
||||||
|
SrcBlockHeight, 1,
|
||||||
|
SrcSwizzle,
|
||||||
|
GalTextureFormat.A8B8G8R8);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureInfo DstTexture = new TextureInfo(
|
TextureInfo DstTexture()
|
||||||
|
{
|
||||||
|
return new TextureInfo(
|
||||||
DstAddress,
|
DstAddress,
|
||||||
DstWidth,
|
DstWidth,
|
||||||
DstHeight,
|
DstHeight,
|
||||||
DstBlockHeight,
|
DstPitch,
|
||||||
DstBlockHeight,
|
DstBlockHeight, 1,
|
||||||
DstSwizzle,
|
DstSwizzle,
|
||||||
GalTextureFormat.A8B8G8R8);
|
GalTextureFormat.A8B8G8R8);
|
||||||
|
}
|
||||||
|
|
||||||
if (IsFbTexture)
|
//TODO: fb -> fb copies, tex -> fb copies, formats other than RGBA8,
|
||||||
|
//make it throw for unimpl stuff (like the copy mode)...
|
||||||
|
if (IsSrcFb && IsDstFb)
|
||||||
{
|
{
|
||||||
//TODO: Change this when the correct frame buffer resolution is used.
|
//Frame Buffer -> Frame Buffer copy.
|
||||||
//Currently, the frame buffer size is hardcoded to 1280x720.
|
Gpu.Renderer.FrameBuffer.Copy(
|
||||||
SrcWidth = 1280;
|
SrcKey,
|
||||||
SrcHeight = 720;
|
DstKey,
|
||||||
|
0,
|
||||||
Gpu.Renderer.FrameBuffer.GetBufferData(Key, (byte[] Buffer) =>
|
0,
|
||||||
{
|
|
||||||
CopyTexture(
|
|
||||||
Vmm,
|
|
||||||
DstTexture,
|
|
||||||
Buffer,
|
|
||||||
SrcWidth,
|
SrcWidth,
|
||||||
SrcHeight);
|
SrcHeight,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
DstWidth,
|
||||||
|
DstHeight);
|
||||||
|
}
|
||||||
|
if (IsSrcFb)
|
||||||
|
{
|
||||||
|
//Frame Buffer -> Texture copy.
|
||||||
|
Gpu.Renderer.FrameBuffer.GetBufferData(SrcKey, (byte[] Buffer) =>
|
||||||
|
{
|
||||||
|
TextureInfo Src = SrcTexture();
|
||||||
|
TextureInfo Dst = DstTexture();
|
||||||
|
|
||||||
|
if (Src.Width != Dst.Width ||
|
||||||
|
Src.Height != Dst.Height)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Texture resizing is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureWriter.Write(Vmm, Dst, Buffer);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if (IsDstFb)
|
||||||
|
{
|
||||||
|
//Texture -> Frame Buffer copy.
|
||||||
|
const GalTextureFormat Format = GalTextureFormat.A8B8G8R8;
|
||||||
|
|
||||||
|
byte[] Buffer = TextureReader.Read(Vmm, SrcTexture());
|
||||||
|
|
||||||
|
Gpu.Renderer.FrameBuffer.SetBufferData(
|
||||||
|
DstKey,
|
||||||
|
DstWidth,
|
||||||
|
DstHeight,
|
||||||
|
Format,
|
||||||
|
Buffer);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
long Size = SrcWidth * SrcHeight * 4;
|
//Texture -> Texture copy.
|
||||||
|
TextureInfo Src = SrcTexture();
|
||||||
|
TextureInfo Dst = DstTexture();
|
||||||
|
|
||||||
byte[] Buffer = Vmm.ReadBytes(SrcAddress, Size);
|
if (Src.Width != Dst.Width ||
|
||||||
|
Src.Height != Dst.Height)
|
||||||
CopyTexture(
|
|
||||||
Vmm,
|
|
||||||
DstTexture,
|
|
||||||
Buffer,
|
|
||||||
SrcWidth,
|
|
||||||
SrcHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CopyTexture(
|
|
||||||
NvGpuVmm Vmm,
|
|
||||||
TextureInfo Texture,
|
|
||||||
byte[] Buffer,
|
|
||||||
int Width,
|
|
||||||
int Height)
|
|
||||||
{
|
{
|
||||||
TextureWriter.Write(Vmm, Texture, Buffer, Width, Height);
|
throw new NotImplementedException("Texture resizing is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureWriter.Write(Vmm, Dst, TextureReader.Read(Vmm, Src));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long MakeInt64From2xInt32(NvGpuEngine2dReg Reg)
|
private long MakeInt64From2xInt32(NvGpuEngine2dReg Reg)
|
||||||
|
|
|
@ -132,10 +132,22 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10);
|
int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10);
|
||||||
int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10);
|
int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10);
|
||||||
|
|
||||||
//Note: Using the Width/Height results seems to give incorrect results.
|
float TX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateX + FbIndex * 4);
|
||||||
//Maybe the size of all frame buffers is hardcoded to screen size? This seems unlikely.
|
float TY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateY + FbIndex * 4);
|
||||||
Gpu.Renderer.FrameBuffer.Create(Key, 1280, 720);
|
|
||||||
|
float SX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleX + FbIndex * 4);
|
||||||
|
float SY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleY + FbIndex * 4);
|
||||||
|
|
||||||
|
int VpX = (int)MathF.Max(0, TX - MathF.Abs(SX));
|
||||||
|
int VpY = (int)MathF.Max(0, TY - MathF.Abs(SY));
|
||||||
|
|
||||||
|
int VpW = (int)(TX + MathF.Abs(SX)) - VpX;
|
||||||
|
int VpH = (int)(TY + MathF.Abs(SY)) - VpY;
|
||||||
|
|
||||||
|
Gpu.Renderer.FrameBuffer.Create(Key, Width, Height);
|
||||||
Gpu.Renderer.FrameBuffer.Bind(Key);
|
Gpu.Renderer.FrameBuffer.Bind(Key);
|
||||||
|
|
||||||
|
Gpu.Renderer.FrameBuffer.SetViewport(VpX, VpY, VpW, VpH);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long[] UploadShaders(NvGpuVmm Vmm)
|
private long[] UploadShaders(NvGpuVmm Vmm)
|
||||||
|
@ -195,8 +207,8 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
Gpu.Renderer.Shader.Bind(Key);
|
Gpu.Renderer.Shader.Bind(Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportScaleX);
|
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
|
||||||
float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportScaleY);
|
float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
|
||||||
|
|
||||||
Gpu.Renderer.Shader.SetFlip(SignX, SignY);
|
Gpu.Renderer.Shader.SetFlip(SignX, SignY);
|
||||||
|
|
||||||
|
@ -220,8 +232,8 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
|
|
||||||
private void SetFrontFace()
|
private void SetFrontFace()
|
||||||
{
|
{
|
||||||
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportScaleX);
|
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
|
||||||
float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportScaleY);
|
float SignY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
|
||||||
|
|
||||||
GalFrontFace FrontFace = (GalFrontFace)ReadRegister(NvGpuEngine3dReg.FrontFace);
|
GalFrontFace FrontFace = (GalFrontFace)ReadRegister(NvGpuEngine3dReg.FrontFace);
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,14 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
FrameBufferNWidth = 0x202,
|
FrameBufferNWidth = 0x202,
|
||||||
FrameBufferNHeight = 0x203,
|
FrameBufferNHeight = 0x203,
|
||||||
FrameBufferNFormat = 0x204,
|
FrameBufferNFormat = 0x204,
|
||||||
ViewportScaleX = 0x280,
|
ViewportNScaleX = 0x280,
|
||||||
ViewportScaleY = 0x281,
|
ViewportNScaleY = 0x281,
|
||||||
ViewportScaleZ = 0x282,
|
ViewportNScaleZ = 0x282,
|
||||||
ViewportTranslateX = 0x283,
|
ViewportNTranslateX = 0x283,
|
||||||
ViewportTranslateY = 0x284,
|
ViewportNTranslateY = 0x284,
|
||||||
ViewportTranslateZ = 0x285,
|
ViewportNTranslateZ = 0x285,
|
||||||
|
ViewportNHoriz = 0x300,
|
||||||
|
ViewportNVert = 0x301,
|
||||||
VertexArrayFirst = 0x35d,
|
VertexArrayFirst = 0x35d,
|
||||||
VertexArrayCount = 0x35e,
|
VertexArrayCount = 0x35e,
|
||||||
ClearDepth = 0x364,
|
ClearDepth = 0x364,
|
||||||
|
|
|
@ -56,8 +56,10 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
int Pitch = (Tic[3] & 0xffff) << 5;
|
int Pitch = (Tic[3] & 0xffff) << 5;
|
||||||
|
|
||||||
int BlockHeightLog2 = (Tic[3] >> 3) & 7;
|
int BlockHeightLog2 = (Tic[3] >> 3) & 7;
|
||||||
|
int TileWidthLog2 = (Tic[3] >> 10) & 7;
|
||||||
|
|
||||||
int BlockHeight = 1 << BlockHeightLog2;
|
int BlockHeight = 1 << BlockHeightLog2;
|
||||||
|
int TileWidth = 1 << TileWidthLog2;
|
||||||
|
|
||||||
int Width = (Tic[4] & 0xffff) + 1;
|
int Width = (Tic[4] & 0xffff) + 1;
|
||||||
int Height = (Tic[5] & 0xffff) + 1;
|
int Height = (Tic[5] & 0xffff) + 1;
|
||||||
|
@ -68,6 +70,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
Height,
|
Height,
|
||||||
Pitch,
|
Pitch,
|
||||||
BlockHeight,
|
BlockHeight,
|
||||||
|
TileWidth,
|
||||||
Swizzle,
|
Swizzle,
|
||||||
Format);
|
Format);
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,14 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
{
|
{
|
||||||
static class TextureHelper
|
static class TextureHelper
|
||||||
{
|
{
|
||||||
public static ISwizzle GetSwizzle(TextureInfo Texture, int Width, int Bpp)
|
public static ISwizzle GetSwizzle(TextureInfo Texture, int BlockWidth, int Bpp)
|
||||||
{
|
{
|
||||||
|
int Width = (Texture.Width + (BlockWidth - 1)) / BlockWidth;
|
||||||
|
|
||||||
|
int AlignMask = Texture.TileWidth * (64 / Bpp) - 1;
|
||||||
|
|
||||||
|
Width = (Width + AlignMask) & ~AlignMask;
|
||||||
|
|
||||||
switch (Texture.Swizzle)
|
switch (Texture.Swizzle)
|
||||||
{
|
{
|
||||||
case TextureSwizzle._1dBuffer:
|
case TextureSwizzle._1dBuffer:
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
public int Pitch { get; private set; }
|
public int Pitch { get; private set; }
|
||||||
|
|
||||||
public int BlockHeight { get; private set; }
|
public int BlockHeight { get; private set; }
|
||||||
|
public int TileWidth { get; private set; }
|
||||||
|
|
||||||
public TextureSwizzle Swizzle { get; private set; }
|
public TextureSwizzle Swizzle { get; private set; }
|
||||||
|
|
||||||
|
@ -29,6 +30,8 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
|
|
||||||
BlockHeight = 16;
|
BlockHeight = 16;
|
||||||
|
|
||||||
|
TileWidth = 1;
|
||||||
|
|
||||||
Swizzle = TextureSwizzle.BlockLinear;
|
Swizzle = TextureSwizzle.BlockLinear;
|
||||||
|
|
||||||
Format = GalTextureFormat.A8B8G8R8;
|
Format = GalTextureFormat.A8B8G8R8;
|
||||||
|
@ -40,6 +43,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
int Height,
|
int Height,
|
||||||
int Pitch,
|
int Pitch,
|
||||||
int BlockHeight,
|
int BlockHeight,
|
||||||
|
int TileWidth,
|
||||||
TextureSwizzle Swizzle,
|
TextureSwizzle Swizzle,
|
||||||
GalTextureFormat Format)
|
GalTextureFormat Format)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +52,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
this.Height = Height;
|
this.Height = Height;
|
||||||
this.Pitch = Pitch;
|
this.Pitch = Pitch;
|
||||||
this.BlockHeight = BlockHeight;
|
this.BlockHeight = BlockHeight;
|
||||||
|
this.TileWidth = TileWidth;
|
||||||
this.Swizzle = Swizzle;
|
this.Swizzle = Swizzle;
|
||||||
this.Format = Format;
|
this.Format = Format;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
|
|
||||||
byte[] Output = new byte[Width * Height];
|
byte[] Output = new byte[Width * Height];
|
||||||
|
|
||||||
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 1);
|
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 1);
|
||||||
|
|
||||||
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
||||||
Memory,
|
Memory,
|
||||||
|
@ -89,7 +89,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
|
|
||||||
byte[] Output = new byte[Width * Height * 2];
|
byte[] Output = new byte[Width * Height * 2];
|
||||||
|
|
||||||
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 2);
|
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
|
||||||
|
|
||||||
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
||||||
Memory,
|
Memory,
|
||||||
|
@ -127,7 +127,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
|
|
||||||
byte[] Output = new byte[Width * Height * 2];
|
byte[] Output = new byte[Width * Height * 2];
|
||||||
|
|
||||||
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 2);
|
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
|
||||||
|
|
||||||
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
||||||
Memory,
|
Memory,
|
||||||
|
@ -164,7 +164,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
|
|
||||||
byte[] Output = new byte[Width * Height * 2];
|
byte[] Output = new byte[Width * Height * 2];
|
||||||
|
|
||||||
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 2);
|
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
|
||||||
|
|
||||||
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
||||||
Memory,
|
Memory,
|
||||||
|
@ -197,7 +197,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
|
|
||||||
byte[] Output = new byte[Width * Height * 4];
|
byte[] Output = new byte[Width * Height * 4];
|
||||||
|
|
||||||
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 4);
|
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 4);
|
||||||
|
|
||||||
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
||||||
Memory,
|
Memory,
|
||||||
|
@ -230,7 +230,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
|
|
||||||
byte[] Output = new byte[Width * Height * 8];
|
byte[] Output = new byte[Width * Height * 8];
|
||||||
|
|
||||||
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 8);
|
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 8);
|
||||||
|
|
||||||
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
||||||
Memory,
|
Memory,
|
||||||
|
@ -263,7 +263,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
|
|
||||||
byte[] Output = new byte[Width * Height * 16];
|
byte[] Output = new byte[Width * Height * 16];
|
||||||
|
|
||||||
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 16);
|
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 16);
|
||||||
|
|
||||||
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
||||||
Memory,
|
Memory,
|
||||||
|
@ -298,7 +298,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
|
|
||||||
byte[] Output = new byte[Width * Height * 8];
|
byte[] Output = new byte[Width * Height * 8];
|
||||||
|
|
||||||
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 8);
|
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 4, 8);
|
||||||
|
|
||||||
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
||||||
Memory,
|
Memory,
|
||||||
|
@ -331,7 +331,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
|
|
||||||
byte[] Output = new byte[Width * Height * 16];
|
byte[] Output = new byte[Width * Height * 16];
|
||||||
|
|
||||||
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 16);
|
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, BlockWidth, 16);
|
||||||
|
|
||||||
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
||||||
Memory,
|
Memory,
|
||||||
|
|
|
@ -6,29 +6,9 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
{
|
{
|
||||||
static class TextureWriter
|
static class TextureWriter
|
||||||
{
|
{
|
||||||
public static void Write(
|
public unsafe static void Write(IAMemory Memory, TextureInfo Texture, byte[] Data)
|
||||||
IAMemory Memory,
|
|
||||||
TextureInfo Texture,
|
|
||||||
byte[] Data,
|
|
||||||
int Width,
|
|
||||||
int Height)
|
|
||||||
{
|
{
|
||||||
switch (Texture.Format)
|
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 4);
|
||||||
{
|
|
||||||
case GalTextureFormat.A8B8G8R8: Write4Bpp(Memory, Texture, Data, Width, Height); break;
|
|
||||||
|
|
||||||
default: throw new NotImplementedException(Texture.Format.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe static void Write4Bpp(
|
|
||||||
IAMemory Memory,
|
|
||||||
TextureInfo Texture,
|
|
||||||
byte[] Data,
|
|
||||||
int Width,
|
|
||||||
int Height)
|
|
||||||
{
|
|
||||||
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 4);
|
|
||||||
|
|
||||||
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
|
||||||
Memory,
|
Memory,
|
||||||
|
@ -38,8 +18,8 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
{
|
{
|
||||||
long InOffs = 0;
|
long InOffs = 0;
|
||||||
|
|
||||||
for (int Y = 0; Y < Height; Y++)
|
for (int Y = 0; Y < Texture.Height; Y++)
|
||||||
for (int X = 0; X < Width; X++)
|
for (int X = 0; X < Texture.Width; X++)
|
||||||
{
|
{
|
||||||
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
|
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
|
||||||
|
|
||||||
|
|
|
@ -279,8 +279,8 @@ namespace Ryujinx.HLE.OsHle.Services.Android
|
||||||
|
|
||||||
private void SendFrameBuffer(ServiceCtx Context, int Slot)
|
private void SendFrameBuffer(ServiceCtx Context, int Slot)
|
||||||
{
|
{
|
||||||
int FbWidth = 1280;
|
int FbWidth = BufferQueue[Slot].Data.Width;
|
||||||
int FbHeight = 720;
|
int FbHeight = BufferQueue[Slot].Data.Height;
|
||||||
|
|
||||||
int NvMapHandle = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x4c);
|
int NvMapHandle = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x4c);
|
||||||
int BufferOffset = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x50);
|
int BufferOffset = BitConverter.ToInt32(BufferQueue[Slot].Data.RawData, 0x50);
|
||||||
|
|
Loading…
Reference in a new issue