diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index de85a8a..398dbe7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -38,12 +38,14 @@ jobs:
apt: g++-aarch64-linux-gnu
toolchain: toolchain-linux-arm64.cmake
# macOS (Intel + Apple Silicon)
- - os: macos-13
+ - os: macos-14
rid: osx-x64
lib: libbasis_block_encoder.dylib
+ osx_arch: x86_64
- os: macos-14
rid: osx-arm64
lib: libbasis_block_encoder.dylib
+ osx_arch: arm64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
@@ -58,6 +60,7 @@ jobs:
args=(-S native -B native/build -DCMAKE_BUILD_TYPE=Release)
[ -n "${{ matrix.platform }}" ] && args+=(-A "${{ matrix.platform }}")
[ -n "${{ matrix.toolchain }}" ] && args+=(-DCMAKE_TOOLCHAIN_FILE="$PWD/native/cmake/${{ matrix.toolchain }}")
+ [ -n "${{ matrix.osx_arch }}" ] && args+=(-DCMAKE_OSX_ARCHITECTURES="${{ matrix.osx_arch }}" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0)
echo "cmake ${args[*]}"
cmake "${args[@]}"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 87f549f..1b98f2c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -33,12 +33,14 @@ jobs:
lib: libbasis_block_encoder.so
apt: g++-aarch64-linux-gnu
toolchain: toolchain-linux-arm64.cmake
- - os: macos-13
+ - os: macos-14
rid: osx-x64
lib: libbasis_block_encoder.dylib
+ osx_arch: x86_64
- os: macos-14
rid: osx-arm64
lib: libbasis_block_encoder.dylib
+ osx_arch: arm64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
@@ -53,6 +55,7 @@ jobs:
args=(-S native -B native/build -DCMAKE_BUILD_TYPE=Release)
[ -n "${{ matrix.platform }}" ] && args+=(-A "${{ matrix.platform }}")
[ -n "${{ matrix.toolchain }}" ] && args+=(-DCMAKE_TOOLCHAIN_FILE="$PWD/native/cmake/${{ matrix.toolchain }}")
+ [ -n "${{ matrix.osx_arch }}" ] && args+=(-DCMAKE_OSX_ARCHITECTURES="${{ matrix.osx_arch }}" -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0)
echo "cmake ${args[*]}"
cmake "${args[@]}"
diff --git a/.idea/.idea.BasisBlockEncoder/.idea/workspace.xml b/.idea/.idea.BasisBlockEncoder/.idea/workspace.xml
deleted file mode 100644
index 3a1545c..0000000
--- a/.idea/.idea.BasisBlockEncoder/.idea/workspace.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1780154502366
-
-
- 1780154502366
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/BasisBlockEncoder/BasisBlockEncoder.csproj b/src/BasisBlockEncoder/BasisBlockEncoder.csproj
index 7e56c23..2b97341 100644
--- a/src/BasisBlockEncoder/BasisBlockEncoder.csproj
+++ b/src/BasisBlockEncoder/BasisBlockEncoder.csproj
@@ -8,7 +8,6 @@
true
true
-
BasisBlockEncoder
0.1.0
BasisBlockEncoder contributors
@@ -17,17 +16,12 @@
MIT
README.md
git
-
- https://github.com/your-org/basis-block-encoder
- https://github.com/your-org/basis-block-encoder
+ https://github.com/nolife99/basis-block-encoder
+ https://github.com/nolife99/basis-block-encoder
true
snupkg
-
$(MSBuildProjectDirectory)/../../runtimes/
diff --git a/src/BasisBlockEncoder/BlockEncoder.cs b/src/BasisBlockEncoder/BlockEncoder.cs
index 9674405..b5076a6 100644
--- a/src/BasisBlockEncoder/BlockEncoder.cs
+++ b/src/BasisBlockEncoder/BlockEncoder.cs
@@ -28,8 +28,7 @@ public static class BlockEncoder
private static int s_initialized; // 0 = no, 1 = yes
///
- /// Initializes the native encoder tables. Idempotent and thread-safe. Optional: encode calls
- /// initialize on first use.
+ /// Initializes the native encoder tables. Idempotent and thread-safe.
///
/// If native initialization fails.
public static void Initialize()
@@ -85,8 +84,8 @@ public static long EncodedSize(BcFormat format, int width, int height)
/// BC4/BC5 source channel 0 (default 0 = R when negative).
/// BC5 source channel 1 (default 1 = G when negative).
public static unsafe void Encode(
- BcFormat format, ReadOnlySpan srcRgba, int width, int height, int strideBytes,
- Span dst, uint flags = 0, int channel0 = -1, int channel1 = -1)
+ BcFormat format, scoped ReadOnlySpan srcRgba, int width, int height, int strideBytes,
+ scoped Span dst, uint flags = 0, int channel0 = -1, int channel1 = -1)
{
if (format == BcFormat.Bc6h)
throw new ArgumentException("Use EncodeBc6h for BC6H (FP16 input).", nameof(format));
@@ -104,28 +103,28 @@ public static unsafe void Encode(
}
/// Encodes a whole RGBA8 surface to BC7.
- public static void EncodeBc7(ReadOnlySpan srcRgba, int width, int height, int strideBytes,
- Span dst, Bc7Flags flags = Bc7Flags.Default) =>
+ public static void EncodeBc7(scoped ReadOnlySpan srcRgba, int width, int height, int strideBytes,
+ scoped Span dst, Bc7Flags flags = Bc7Flags.Default) =>
Encode(BcFormat.Bc7, srcRgba, width, height, strideBytes, dst, (uint)flags);
/// Encodes a whole RGBA8 surface to BC1 (color only; alpha is ignored).
- public static void EncodeBc1(ReadOnlySpan srcRgba, int width, int height, int strideBytes,
- Span dst, Bc1Quality quality = Bc1Quality.HighQuality) =>
+ public static void EncodeBc1(scoped ReadOnlySpan srcRgba, int width, int height, int strideBytes,
+ scoped Span dst, Bc1Quality quality = Bc1Quality.HighQuality) =>
Encode(BcFormat.Bc1, srcRgba, width, height, strideBytes, dst, (uint)quality);
/// Encodes a whole RGBA8 surface to BC3 (BC4 alpha + BC1 color).
- public static void EncodeBc3(ReadOnlySpan srcRgba, int width, int height, int strideBytes,
- Span dst, Bc1Quality quality = Bc1Quality.HighQuality) =>
+ public static void EncodeBc3(scoped ReadOnlySpan srcRgba, int width, int height, int strideBytes,
+ scoped Span dst, Bc1Quality quality = Bc1Quality.HighQuality) =>
Encode(BcFormat.Bc3, srcRgba, width, height, strideBytes, dst, (uint)quality);
/// Encodes a single channel of a whole RGBA8 surface to BC4.
- public static void EncodeBc4(ReadOnlySpan srcRgba, int width, int height, int strideBytes,
- Span dst, int channel = 0) =>
+ public static void EncodeBc4(scoped ReadOnlySpan srcRgba, int width, int height, int strideBytes,
+ scoped Span dst, int channel = 0) =>
Encode(BcFormat.Bc4, srcRgba, width, height, strideBytes, dst, 0, channel, -1);
/// Encodes two channels of a whole RGBA8 surface to BC5 (red+green by default).
- public static void EncodeBc5(ReadOnlySpan srcRgba, int width, int height, int strideBytes,
- Span dst, int channel0 = 0, int channel1 = 1) =>
+ public static void EncodeBc5(scoped ReadOnlySpan srcRgba, int width, int height, int strideBytes,
+ scoped Span dst, int channel0 = 0, int channel1 = 1) =>
Encode(BcFormat.Bc5, srcRgba, width, height, strideBytes, dst, 0, channel0, channel1);
// -------------------------------------------------------------------------------------------
@@ -139,8 +138,8 @@ public static void EncodeBc5(ReadOnlySpan srcRgba, int width, int height,
/// that tracks the destination offset for you.
///
public static unsafe void EncodeRows(
- BcFormat format, ReadOnlySpan srcRgba, int width, int pixelRows, int strideBytes,
- Span dst, uint flags = 0, int channel0 = -1, int channel1 = -1)
+ BcFormat format, scoped ReadOnlySpan srcRgba, int width, int pixelRows, int strideBytes,
+ scoped Span dst, uint flags = 0, int channel0 = -1, int channel1 = -1)
{
if (format == BcFormat.Bc6h)
throw new ArgumentException("Use EncodeBc6hRows for BC6H (FP16 input).", nameof(format));
@@ -166,7 +165,7 @@ public static unsafe void EncodeRows(
/// (64 bytes) in raster order; receives bytes.
///
public static unsafe void EncodeBlock(
- BcFormat format, ReadOnlySpan block16Rgba, Span dst,
+ BcFormat format, scoped ReadOnlySpan block16Rgba, scoped Span dst,
uint flags = 0, int channel0 = -1, int channel1 = -1)
{
if (format == BcFormat.Bc6h)
@@ -199,8 +198,8 @@ public static unsafe void EncodeBlock(
/// Source pixels: width*height*3 FP16 values.
/// Bytes between rows (>= *6).
public static unsafe void EncodeBc6h(
- ReadOnlySpan srcRgbHalf, int width, int height, int strideBytes,
- Span dst, Bc6hQuality quality = Bc6hQuality.Default)
+ scoped ReadOnlySpan srcRgbHalf, int width, int height, int strideBytes,
+ scoped Span dst, Bc6hQuality quality = Bc6hQuality.Default)
{
ValidateBc6h(srcRgbHalf, width, height, strideBytes, dst);
EnsureInitialized();
@@ -219,14 +218,14 @@ public static unsafe void EncodeBc6h(
/// reinterprets the span as raw FP16 bits.
///
public static void EncodeBc6h(
- ReadOnlySpan srcRgbHalf, int width, int height, int strideBytes,
- Span dst, Bc6hQuality quality = Bc6hQuality.Default) =>
+ scoped ReadOnlySpan srcRgbHalf, int width, int height, int strideBytes,
+ scoped Span dst, Bc6hQuality quality = Bc6hQuality.Default) =>
EncodeBc6h(MemoryMarshal.Cast(srcRgbHalf), width, height, strideBytes, dst, quality);
/// Streaming band variant of .
public static unsafe void EncodeBc6hRows(
- ReadOnlySpan srcRgbHalf, int width, int pixelRows, int strideBytes,
- Span dst, Bc6hQuality quality = Bc6hQuality.Default)
+ scoped ReadOnlySpan srcRgbHalf, int width, int pixelRows, int strideBytes,
+ scoped Span dst, Bc6hQuality quality = Bc6hQuality.Default)
{
ValidateBc6hRows(srcRgbHalf, width, pixelRows, strideBytes, dst);
EnsureInitialized();
@@ -242,8 +241,8 @@ public static unsafe void EncodeBc6hRows(
/// Streaming band variant accepting a span.
public static void EncodeBc6hRows(
- ReadOnlySpan srcRgbHalf, int width, int pixelRows, int strideBytes,
- Span dst, Bc6hQuality quality = Bc6hQuality.Default) =>
+ scoped ReadOnlySpan srcRgbHalf, int width, int pixelRows, int strideBytes,
+ scoped Span dst, Bc6hQuality quality = Bc6hQuality.Default) =>
EncodeBc6hRows(MemoryMarshal.Cast(srcRgbHalf), width, pixelRows, strideBytes, dst, quality);
///
@@ -251,7 +250,7 @@ public static void EncodeBc6hRows(
/// (48 FP16 values) in raster order; receives 16 bytes.
///
public static unsafe void EncodeBc6hBlock(
- ReadOnlySpan block48RgbHalf, Span dst, Bc6hQuality quality = Bc6hQuality.Default)
+ scoped ReadOnlySpan block48RgbHalf, scoped Span dst, Bc6hQuality quality = Bc6hQuality.Default)
{
if (block48RgbHalf.Length < 48)
throw new ArgumentException("A 4x4 RGB FP16 block is 48 halfs.", nameof(block48RgbHalf));
@@ -270,15 +269,15 @@ public static unsafe void EncodeBc6hBlock(
/// Encodes a single 4x4 BC6H block from a span.
public static void EncodeBc6hBlock(
- ReadOnlySpan block48RgbHalf, Span dst, Bc6hQuality quality = Bc6hQuality.Default) =>
+ scoped ReadOnlySpan block48RgbHalf, scoped Span dst, Bc6hQuality quality = Bc6hQuality.Default) =>
EncodeBc6hBlock(MemoryMarshal.Cast(block48RgbHalf), dst, quality);
// -------------------------------------------------------------------------------------------
// Validation helpers
// -------------------------------------------------------------------------------------------
- private static void ValidateLdr(BcFormat format, ReadOnlySpan src, int width, int height,
- int strideBytes, Span dst)
+ private static void ValidateLdr(BcFormat format, scoped ReadOnlySpan src, int width, int height,
+ int strideBytes, scoped Span dst)
{
if (width <= 0 || height <= 0)
throw new ArgumentOutOfRangeException(width <= 0 ? nameof(width) : nameof(height), "Dimensions must be positive.");
@@ -288,8 +287,8 @@ private static void ValidateLdr(BcFormat format, ReadOnlySpan src, int wid
RequireDst(dst.Length, EncodedSize(format, width, height));
}
- private static void ValidateLdrRows(BcFormat format, ReadOnlySpan src, int width, int pixelRows,
- int strideBytes, Span dst)
+ private static void ValidateLdrRows(BcFormat format, scoped ReadOnlySpan src, int width, int pixelRows,
+ int strideBytes, scoped Span dst)
{
if (width <= 0 || pixelRows <= 0)
throw new ArgumentOutOfRangeException(width <= 0 ? nameof(width) : nameof(pixelRows), "Dimensions must be positive.");
@@ -299,7 +298,7 @@ private static void ValidateLdrRows(BcFormat format, ReadOnlySpan src, int
RequireDst(dst.Length, EncodedSize(format, width, pixelRows));
}
- private static void ValidateBc6h(ReadOnlySpan src, int width, int height, int strideBytes, Span dst)
+ private static void ValidateBc6h(scoped ReadOnlySpan src, int width, int height, int strideBytes, scoped Span dst)
{
if (width <= 0 || height <= 0)
throw new ArgumentOutOfRangeException(width <= 0 ? nameof(width) : nameof(height), "Dimensions must be positive.");
@@ -309,7 +308,7 @@ private static void ValidateBc6h(ReadOnlySpan src, int width, int height
RequireDst(dst.Length, EncodedSize(BcFormat.Bc6h, width, height));
}
- private static void ValidateBc6hRows(ReadOnlySpan src, int width, int pixelRows, int strideBytes, Span dst)
+ private static void ValidateBc6hRows(scoped ReadOnlySpan src, int width, int pixelRows, int strideBytes, scoped Span dst)
{
if (width <= 0 || pixelRows <= 0)
throw new ArgumentOutOfRangeException(width <= 0 ? nameof(width) : nameof(pixelRows), "Dimensions must be positive.");
diff --git a/src/BasisBlockEncoder/BlockRowStreamWriter.cs b/src/BasisBlockEncoder/BlockRowStreamWriter.cs
index d2c63ca..7f6b54b 100644
--- a/src/BasisBlockEncoder/BlockRowStreamWriter.cs
+++ b/src/BasisBlockEncoder/BlockRowStreamWriter.cs
@@ -66,7 +66,7 @@ public BlockRowStreamWriter(BcFormat format, int width, int height, Memory
/// Encodes the next rows from (RGBA8,
/// per row) into the destination.
///
- public void WriteRows(ReadOnlySpan bandRgba, int pixelRows, int strideBytes)
+ public void WriteRows(scoped ReadOnlySpan bandRgba, int pixelRows, int strideBytes)
{
if (IsComplete)
throw new InvalidOperationException("All rows have already been written.");
@@ -129,7 +129,7 @@ public Bc6hBlockRowStreamWriter(int width, int height, Memory dst,
public bool IsComplete => _pixelRowsDone >= _height;
/// Encodes the next rows from an RGB FP16 band.
- public void WriteRows(ReadOnlySpan bandRgbHalf, int pixelRows, int strideBytes)
+ public void WriteRows(scoped ReadOnlySpan bandRgbHalf, int pixelRows, int strideBytes)
{
if (IsComplete)
throw new InvalidOperationException("All rows have already been written.");
@@ -149,6 +149,6 @@ public void WriteRows(ReadOnlySpan bandRgbHalf, int pixelRows, int strid
}
/// Encodes the next band from a span.
- public void WriteRows(ReadOnlySpan bandRgbHalf, int pixelRows, int strideBytes) =>
+ public void WriteRows(scoped ReadOnlySpan bandRgbHalf, int pixelRows, int strideBytes) =>
WriteRows(System.Runtime.InteropServices.MemoryMarshal.Cast(bandRgbHalf), pixelRows, strideBytes);
}