Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Assets/dll/librashader.dll
Binary file not shown.
38 changes: 37 additions & 1 deletion src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// TODO
// TODO
// we could flag textures as 'actually' render targets (keep a reference to the render target?) which could allow us to convert between them more quickly in some cases

using System.Collections.Generic;
Expand Down Expand Up @@ -112,6 +112,7 @@ protected DisplayManagerBase(
// `_apiHawkIDTo2DRenderer` is a new empty dict, members are lazily-initialised

RefreshUserShader();
RefreshLibrashader();
}

public void UpdateGlobals(Config config, IEmulator emulator)
Expand Down Expand Up @@ -158,6 +159,8 @@ public void Dispose()
s?.Dispose();
}

_librashaderFilter?.Dispose();

_theOneFont?.Dispose();
_renderer.Dispose();
}
Expand Down Expand Up @@ -222,6 +225,8 @@ private StringRenderer Font

private RetroShaderChain _shaderChainUser;

private LibrashaderFilter _librashaderFilter;

public abstract void ActivateOpenGLContext();

protected abstract void ActivateGraphicsControlContext();
Expand All @@ -231,6 +236,7 @@ private StringRenderer Font
public void RefreshUserShader()
{
_shaderChainUser?.Dispose();
_shaderChainUser = null;
if (File.Exists(GlobalConfig.DispUserFilterPath))
{
var fi = new FileInfo(GlobalConfig.DispUserFilterPath);
Expand All @@ -239,6 +245,25 @@ public void RefreshUserShader()
}
}

public void RefreshLibrashader()
{
Console.WriteLine($"[librashader] RefreshLibrashader called, path: {GlobalConfig.DispUserFilterPath}");
_librashaderFilter?.Dispose();
_librashaderFilter = null;
if (_gl is IGL_OpenGL && File.Exists(GlobalConfig.DispUserFilterPath))
{
Console.WriteLine("[librashader] Creating LibrashaderFilter");
_librashaderFilter = new LibrashaderFilter(GlobalConfig.DispUserFilterPath);
}
else
{
if (_gl is not IGL_OpenGL)
Console.WriteLine("[librashader] GL is not IGL_OpenGL, skipping librashader");
else if (!File.Exists(GlobalConfig.DispUserFilterPath))
Console.WriteLine("[librashader] Shader preset file not found");
}
}

private (int Left, int Top, int Right, int Bottom) CalculateCompleteContentPadding(bool user, bool source)
{
var padding = (Left: 0, Top: 0, Right: 0, Bottom: 0);
Expand Down Expand Up @@ -282,6 +307,7 @@ private FilterProgram BuildDefaultChain(Size chainInSize, Size chainOutSize, boo
// select user special FX shader chain
KeyValuePair<string, float>[] selectedChainProperties = null;
RetroShaderChain selectedChain = null;
bool useLibrashader = false;
switch (GlobalConfig.TargetDisplayFilter)
{
case 1 when _shaderChainHq2X is { Available: true }:
Expand All @@ -294,11 +320,15 @@ private FilterProgram BuildDefaultChain(Size chainInSize, Size chainOutSize, boo
case 3 when _shaderChainUser is { Available: true }:
selectedChain = _shaderChainUser;
break;
case 4 when _librashaderFilter != null:
useLibrashader = true;
break;
}

if (!includeUserFilters)
{
selectedChain = null;
useLibrashader = false;
}

var fCoreScreenControl = CreateCoreScreenControl();
Expand Down Expand Up @@ -362,6 +392,12 @@ private FilterProgram BuildDefaultChain(Size chainInSize, Size chainOutSize, boo
AppendRetroShaderChain(chain, "retroShader", selectedChain, selectedChainProperties);
}

// add librashader filter
if (useLibrashader)
{
chain.AddFilter(_librashaderFilter, "librashader");
}

// AutoPrescale makes no sense for a None final filter
if (GlobalConfig.DispAutoPrescale && GlobalConfig.DispFinalFilter != (int)FinalPresentation.eFilterOption.None)
{
Expand Down
127 changes: 127 additions & 0 deletions src/BizHawk.Client.Common/DisplayManager/Filters/Librashader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
using System.Runtime.InteropServices;
using System.Text;

using BizHawk.Common;

namespace BizHawk.Client.Common.Filters
{
public static unsafe class Librashader
{
private const CallingConvention CC = CallingConvention.Cdecl;
private static bool _loaded = false;

public static bool IsLoaded => _loaded;

public static bool Load()
{
if (_loaded) return true;

Util.DebugWriteLine("[librashader] Attempting to load librashader.dll...");
try
{
libra_instance_abi_version();
Util.DebugWriteLine("[librashader] Successfully loaded librashader.dll");
_loaded = true;
return true;
}
catch (DllNotFoundException)
{
Util.DebugWriteLine("[librashader] Failed to load librashader.dll");
return false;
}
}

[DllImport("librashader", CallingConvention = CC)]
public static extern IntPtr libra_instance_abi_version();

[DllImport("librashader", CallingConvention = CC)]
public static extern IntPtr libra_instance_api_version();

[DllImport("librashader", CallingConvention = CC)]
public static extern IntPtr libra_preset_create(byte* filename, out IntPtr preset);

[DllImport("librashader", CallingConvention = CC)]
public static extern int libra_preset_free(ref IntPtr preset);

[DllImport("librashader", CallingConvention = CC)]
public static extern int libra_error_free(ref IntPtr error);

[DllImport("librashader", CallingConvention = CC)]
public static extern int libra_error_print(IntPtr error);

[DllImport("librashader", CallingConvention = CC)]
public static extern int libra_error_errno(IntPtr error);

[DllImport("librashader", CallingConvention = CC)]
public static extern IntPtr libra_gl_filter_chain_create(
ref IntPtr preset,
IntPtr loader,
[In] ref filter_chain_gl_opt_t options,
out IntPtr chain);

[DllImport("librashader", CallingConvention = CC)]
public static extern int libra_gl_filter_chain_frame(
ref IntPtr chain,
UIntPtr frame_count,
libra_image_gl_t image,
libra_image_gl_t output,
IntPtr viewport,
IntPtr mvp,
IntPtr options);

[DllImport("librashader", CallingConvention = CC)]
public static extern int libra_gl_filter_chain_free(ref IntPtr chain);

public static IntPtr PresetCreate(string filename, out IntPtr preset)
{
byte[] bytes = Encoding.UTF8.GetBytes(filename + "\0");
fixed (byte* ptr = bytes)
{
return libra_preset_create(ptr, out preset);
}
}

[StructLayout(LayoutKind.Sequential)]
public struct filter_chain_gl_opt_t
{
public UIntPtr version;
public ushort glsl_version;
[MarshalAs(UnmanagedType.U1)]
public bool use_dsa;
[MarshalAs(UnmanagedType.U1)]
public bool force_no_mipmaps;
[MarshalAs(UnmanagedType.U1)]
public bool disable_cache;
}

[StructLayout(LayoutKind.Sequential)]
public struct libra_image_gl_t
{
public uint handle;
public uint format;
public uint width;
public uint height;
}

[StructLayout(LayoutKind.Sequential)]
public struct libra_viewport_t
{
public float x;
public float y;
public uint width;
public uint height;
}

public static filter_chain_gl_opt_t CreateDefaultOptions()
{
return new filter_chain_gl_opt_t
{
version = new UIntPtr(1),
glsl_version = 330,
use_dsa = false,
force_no_mipmaps = false,
disable_cache = false,
};
}
}
}
Loading