aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Texture
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-12-05 17:34:47 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commite25b7c9848b6ec486eb513297b5c536857665c7f (patch)
treec1ccb6c58bed0f7ece835359516330104feb8f4d /Ryujinx.Graphics.Texture
parent6a98c643cabeea25dc42e19fe475a687a034a532 (diff)
Initial support for the guest OpenGL driver (NVIDIA and Nouveau)
Diffstat (limited to 'Ryujinx.Graphics.Texture')
-rw-r--r--Ryujinx.Graphics.Texture/LayoutConverter.cs129
1 files changed, 121 insertions, 8 deletions
diff --git a/Ryujinx.Graphics.Texture/LayoutConverter.cs b/Ryujinx.Graphics.Texture/LayoutConverter.cs
index ef80144e..c270b494 100644
--- a/Ryujinx.Graphics.Texture/LayoutConverter.cs
+++ b/Ryujinx.Graphics.Texture/LayoutConverter.cs
@@ -7,7 +7,7 @@ namespace Ryujinx.Graphics.Texture
{
public static class LayoutConverter
{
- private const int AlignmentSize = 4;
+ private const int HostStrideAlignment = 4;
public static Span<byte> ConvertBlockLinearToLinear(
int width,
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Texture
int gobBlocksInZ,
int gobBlocksInTileX,
SizeInfo sizeInfo,
- Span<byte> data)
+ ReadOnlySpan<byte> data)
{
int outSize = GetTextureSize(
width,
@@ -62,7 +62,7 @@ namespace Ryujinx.Graphics.Texture
mipGobBlocksInZ >>= 1;
}
- int stride = BitUtils.AlignUp(w * bytesPerPixel, AlignmentSize);
+ int stride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
int wAligned = BitUtils.AlignUp(w, wAlignment);
BlockLinearLayout layoutConverter = new BlockLinearLayout(
@@ -104,17 +104,17 @@ namespace Ryujinx.Graphics.Texture
int blockHeight,
int stride,
int bytesPerPixel,
- Span<byte> data)
+ ReadOnlySpan<byte> data)
{
- int outOffs = 0;
-
int w = BitUtils.DivRoundUp(width, blockWidth);
int h = BitUtils.DivRoundUp(height, blockHeight);
- int outStride = BitUtils.AlignUp(w * bytesPerPixel, AlignmentSize);
+ int outStride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
Span<byte> output = new byte[h * outStride];
+ int outOffs = 0;
+
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
@@ -132,6 +132,119 @@ namespace Ryujinx.Graphics.Texture
return output;
}
+ public static Span<byte> ConvertLinearToBlockLinear(
+ int width,
+ int height,
+ int depth,
+ int levels,
+ int layers,
+ int blockWidth,
+ int blockHeight,
+ int bytesPerPixel,
+ int gobBlocksInY,
+ int gobBlocksInZ,
+ int gobBlocksInTileX,
+ SizeInfo sizeInfo,
+ ReadOnlySpan<byte> data)
+ {
+ Span<byte> output = new byte[sizeInfo.TotalSize];
+
+ int inOffs = 0;
+
+ int wAlignment = gobBlocksInTileX * (GobStride / bytesPerPixel);
+
+ int mipGobBlocksInY = gobBlocksInY;
+ int mipGobBlocksInZ = gobBlocksInZ;
+
+ for (int level = 0; level < levels; level++)
+ {
+ int w = Math.Max(1, width >> level);
+ int h = Math.Max(1, height >> level);
+ int d = Math.Max(1, depth >> level);
+
+ w = BitUtils.DivRoundUp(w, blockWidth);
+ h = BitUtils.DivRoundUp(h, blockHeight);
+
+ while (h <= (mipGobBlocksInY >> 1) * GobHeight && mipGobBlocksInY != 1)
+ {
+ mipGobBlocksInY >>= 1;
+ }
+
+ while (d <= (mipGobBlocksInZ >> 1) && mipGobBlocksInZ != 1)
+ {
+ mipGobBlocksInZ >>= 1;
+ }
+
+ int stride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
+ int wAligned = BitUtils.AlignUp(w, wAlignment);
+
+ BlockLinearLayout layoutConverter = new BlockLinearLayout(
+ wAligned,
+ h,
+ d,
+ mipGobBlocksInY,
+ mipGobBlocksInZ,
+ bytesPerPixel);
+
+ for (int layer = 0; layer < layers; layer++)
+ {
+ int outBaseOffset = layer * sizeInfo.LayerSize + sizeInfo.GetMipOffset(level);
+
+ for (int z = 0; z < d; z++)
+ for (int y = 0; y < h; y++)
+ {
+ for (int x = 0; x < w; x++)
+ {
+ int offset = outBaseOffset + layoutConverter.GetOffset(x, y, z);
+
+ Span<byte> dest = output.Slice(offset, bytesPerPixel);
+
+ data.Slice(inOffs + x * bytesPerPixel, bytesPerPixel).CopyTo(dest);
+ }
+
+ inOffs += stride;
+ }
+ }
+ }
+
+ return output;
+ }
+
+ public static Span<byte> ConvertLinearToLinearStrided(
+ int width,
+ int height,
+ int blockWidth,
+ int blockHeight,
+ int stride,
+ int bytesPerPixel,
+ ReadOnlySpan<byte> data)
+ {
+ int w = BitUtils.DivRoundUp(width, blockWidth);
+ int h = BitUtils.DivRoundUp(height, blockHeight);
+
+ int inStride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
+
+ Span<byte> output = new byte[h * stride];
+
+ int inOffs = 0;
+
+ for (int y = 0; y < h; y++)
+ {
+ for (int x = 0; x < w; x++)
+ {
+ int offset = y * stride + x * bytesPerPixel;
+
+ Span<byte> dest = output.Slice(offset, bytesPerPixel);
+
+ data.Slice(inOffs + x * bytesPerPixel, bytesPerPixel).CopyTo(dest);
+ }
+
+ inOffs += inStride;
+ }
+
+ return output;
+ }
+
private static int GetTextureSize(
int width,
int height,
@@ -153,7 +266,7 @@ namespace Ryujinx.Graphics.Texture
w = BitUtils.DivRoundUp(w, blockWidth);
h = BitUtils.DivRoundUp(h, blockHeight);
- int stride = BitUtils.AlignUp(w * bytesPerPixel, AlignmentSize);
+ int stride = BitUtils.AlignUp(w * bytesPerPixel, HostStrideAlignment);
layerSize += stride * h * d;
}