ryujinx/src/Ryujinx.Graphics.Texture/BCnEncoder.cs
jhorv 268c9aecf8
Texture loading: reduce memory allocations (#6623)
* rebase

* add methods Ryyjinx.Common EmbeddedResources and SteamUtils

* GAL changes - change SetData() methods and ThreadedTexture commands to use IMemoryOwner<byte> instead of SpanOrArray<byte>

* Ryujinx.Graphics.Texture: change texture conversion methods to return IMemoryOwner<byte> and allocate from ByteMemoryPool

* Ryujinx.Graphics.OpenGL: update ITexture and Texture-like types with SetData() methods to take IMemoryOwner<byte> instead of SpanOrArray<byte>

* Ryujinx.Graphics.Vulkan: update ITexture and Texture-like types with SetData() methods to take IMemoryOwner<byte> instead of SpanOrArray<byte>

* Ryujinx.Graphics.Gpu: update ITexture and Texture-like types with SetData() methods to take IMemoryOwner<byte> instead of SpanOrArray<byte>

* Remove now-unused SpanOrArray<T>

* post-rebase cleanup

* PixelConverter: remove unsafe modifier on safe methods, and remove one unnecessary cast

* use ByteMemoryPool.Rent() in GetWritableRegion() impls

* fix formatting, rename `ReadRentedMemory()` to `ReadFileToRentedMemory()``

* Texture.ConvertToHostCompatibleFormat(): dispose of `result` in Astc decode branch
2024-04-14 17:06:14 -03:00

62 lines
1.9 KiB
C#

using Ryujinx.Common;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Texture.Encoders;
using System;
using System.Buffers;
namespace Ryujinx.Graphics.Texture
{
public static class BCnEncoder
{
private const int BlockWidth = 4;
private const int BlockHeight = 4;
public static IMemoryOwner<byte> EncodeBC7(Memory<byte> data, int width, int height, int depth, int levels, int layers)
{
int size = 0;
for (int l = 0; l < levels; l++)
{
int w = BitUtils.DivRoundUp(Math.Max(1, width >> l), BlockWidth);
int h = BitUtils.DivRoundUp(Math.Max(1, height >> l), BlockHeight);
size += w * h * 16 * Math.Max(1, depth >> l) * layers;
}
IMemoryOwner<byte> output = ByteMemoryPool.Rent(size);
Memory<byte> outputMemory = output.Memory;
int imageBaseIOffs = 0;
int imageBaseOOffs = 0;
for (int l = 0; l < levels; l++)
{
int w = BitUtils.DivRoundUp(width, BlockWidth);
int h = BitUtils.DivRoundUp(height, BlockHeight);
for (int l2 = 0; l2 < layers; l2++)
{
for (int z = 0; z < depth; z++)
{
BC7Encoder.Encode(
outputMemory[imageBaseOOffs..],
data[imageBaseIOffs..],
width,
height,
EncodeMode.Fast | EncodeMode.Multithreaded);
imageBaseIOffs += width * height * 4;
imageBaseOOffs += w * h * 16;
}
}
width = Math.Max(1, width >> 1);
height = Math.Max(1, height >> 1);
depth = Math.Max(1, depth >> 1);
}
return output;
}
}
}