mirror of
https://github.com/par274/sharpemu.git
synced 2026-09-01 14:21:04 +08:00
Update native Vulkan backend interface
This commit is contained in:
@@ -12,6 +12,9 @@ namespace SharpEmu.Libs.Gpu.NativeVulkan;
|
|||||||
/// <summary>Native C++ Vulkan implementation of the guest-domain GPU seam.</summary>
|
/// <summary>Native C++ Vulkan implementation of the guest-domain GPU seam.</summary>
|
||||||
internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
|
internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
|
||||||
{
|
{
|
||||||
|
private static readonly IGuestCompiledShader DepthOnlyFragmentShader =
|
||||||
|
new VulkanCompiledGuestShader(SpirvFixedShaders.CreateDepthOnlyFragment());
|
||||||
|
|
||||||
private readonly object _startGate = new();
|
private readonly object _startGate = new();
|
||||||
private readonly BlockingCollection<Action<nint>> _commands = new(new ConcurrentQueue<Action<nint>>(), 256);
|
private readonly BlockingCollection<Action<nint>> _commands = new(new ConcurrentQueue<Action<nint>>(), 256);
|
||||||
private readonly ManualResetEventSlim _ready = new(false);
|
private readonly ManualResetEventSlim _ready = new(false);
|
||||||
@@ -48,34 +51,43 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
|
|||||||
|
|
||||||
public bool TryCompileVertexShader(Gen5ShaderState state, Gen5ShaderEvaluation evaluation,
|
public bool TryCompileVertexShader(Gen5ShaderState state, Gen5ShaderEvaluation evaluation,
|
||||||
out IGuestCompiledShader? shader, out string error, int globalBufferBase = 0,
|
out IGuestCompiledShader? shader, out string error, int globalBufferBase = 0,
|
||||||
int totalGlobalBufferCount = -1, int imageBindingBase = 0, int scalarRegisterBufferIndex = -1)
|
int totalGlobalBufferCount = -1, int imageBindingBase = 0, int scalarRegisterBufferIndex = -1,
|
||||||
|
int requiredVertexOutputCount = 0, ulong storageBufferOffsetAlignment = 1)
|
||||||
{
|
{
|
||||||
shader = null;
|
shader = null;
|
||||||
if (!Gen5SpirvTranslator.TryCompileVertexShader(state, evaluation, out var compiled, out error,
|
if (!Gen5SpirvTranslator.TryCompileVertexShader(state, evaluation, out var compiled, out error,
|
||||||
globalBufferBase, totalGlobalBufferCount, imageBindingBase, scalarRegisterBufferIndex)) return false;
|
globalBufferBase, totalGlobalBufferCount, imageBindingBase, scalarRegisterBufferIndex,
|
||||||
|
requiredVertexOutputCount, storageBufferOffsetAlignment)) return false;
|
||||||
shader = new VulkanCompiledGuestShader(compiled.Spirv); return true;
|
shader = new VulkanCompiledGuestShader(compiled.Spirv); return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryCompilePixelShader(Gen5ShaderState state, Gen5ShaderEvaluation evaluation,
|
public bool TryCompilePixelShader(Gen5ShaderState state, Gen5ShaderEvaluation evaluation,
|
||||||
IReadOnlyList<Gen5PixelOutputBinding> outputs, out IGuestCompiledShader? shader, out string error,
|
IReadOnlyList<Gen5PixelOutputBinding> outputs, out IGuestCompiledShader? shader, out string error,
|
||||||
int globalBufferBase = 0, int totalGlobalBufferCount = -1, int imageBindingBase = 0,
|
int globalBufferBase = 0, int totalGlobalBufferCount = -1, int imageBindingBase = 0,
|
||||||
int scalarRegisterBufferIndex = -1)
|
int scalarRegisterBufferIndex = -1, uint pixelInputEnable = 0, uint pixelInputAddress = 0,
|
||||||
|
ulong storageBufferOffsetAlignment = 1)
|
||||||
{
|
{
|
||||||
shader = null;
|
shader = null;
|
||||||
if (!Gen5SpirvTranslator.TryCompilePixelShader(state, evaluation, outputs, out var compiled, out error,
|
if (!Gen5SpirvTranslator.TryCompilePixelShader(state, evaluation, outputs, out var compiled, out error,
|
||||||
globalBufferBase, totalGlobalBufferCount, imageBindingBase, scalarRegisterBufferIndex)) return false;
|
globalBufferBase, totalGlobalBufferCount, imageBindingBase, scalarRegisterBufferIndex,
|
||||||
|
pixelInputEnable, pixelInputAddress, storageBufferOffsetAlignment)) return false;
|
||||||
shader = new VulkanCompiledGuestShader(compiled.Spirv); return true;
|
shader = new VulkanCompiledGuestShader(compiled.Spirv); return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryCompileComputeShader(Gen5ShaderState state, Gen5ShaderEvaluation evaluation,
|
public bool TryCompileComputeShader(Gen5ShaderState state, Gen5ShaderEvaluation evaluation,
|
||||||
uint localSizeX, uint localSizeY, uint localSizeZ, out IGuestCompiledShader? shader, out string error)
|
uint localSizeX, uint localSizeY, uint localSizeZ, out IGuestCompiledShader? shader, out string error,
|
||||||
|
int totalGlobalBufferCount = -1, int initialScalarBufferIndex = -1, uint waveLaneCount = 32,
|
||||||
|
ulong storageBufferOffsetAlignment = 1)
|
||||||
{
|
{
|
||||||
shader = null;
|
shader = null;
|
||||||
if (!Gen5SpirvTranslator.TryCompileComputeShader(state, evaluation, localSizeX, localSizeY, localSizeZ,
|
if (!Gen5SpirvTranslator.TryCompileComputeShader(state, evaluation, localSizeX, localSizeY, localSizeZ,
|
||||||
out var compiled, out error)) return false;
|
out var compiled, out error, totalGlobalBufferCount, initialScalarBufferIndex, waveLaneCount,
|
||||||
|
storageBufferOffsetAlignment)) return false;
|
||||||
shader = new VulkanCompiledGuestShader(compiled.Spirv); return true;
|
shader = new VulkanCompiledGuestShader(compiled.Spirv); return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IGuestCompiledShader GetDepthOnlyFragmentShader() => DepthOnlyFragmentShader;
|
||||||
|
|
||||||
public void HideSplashScreen() { }
|
public void HideSplashScreen() { }
|
||||||
|
|
||||||
public void Submit(byte[] bgraFrame, uint width, uint height)
|
public void Submit(byte[] bgraFrame, uint width, uint height)
|
||||||
@@ -118,7 +130,7 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
|
|||||||
uint attributeCount, IReadOnlyList<GuestRenderTarget> targets, IGuestCompiledShader? vertexShader = null,
|
uint attributeCount, IReadOnlyList<GuestRenderTarget> targets, IGuestCompiledShader? vertexShader = null,
|
||||||
uint vertexCount = 3, uint instanceCount = 1, uint primitiveType = 4,
|
uint vertexCount = 3, uint instanceCount = 1, uint primitiveType = 4,
|
||||||
GuestIndexBuffer? indexBuffer = null, IReadOnlyList<GuestVertexBuffer>? vertexBuffers = null,
|
GuestIndexBuffer? indexBuffer = null, IReadOnlyList<GuestVertexBuffer>? vertexBuffers = null,
|
||||||
GuestRenderState? renderState = null)
|
GuestRenderState? renderState = null, GuestDepthTarget? depthTarget = null, ulong shaderAddress = 0)
|
||||||
{
|
{
|
||||||
if (targets.Count == 0) return;
|
if (targets.Count == 0) return;
|
||||||
EnsureStarted(targets[0].Width, targets[0].Height);
|
EnsureStarted(targets[0].Width, targets[0].Height);
|
||||||
@@ -130,9 +142,25 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
|
|||||||
primitiveType, indexBuffer, vertexCopy, renderState, targetCopy, true)));
|
primitiveType, indexBuffer, vertexCopy, renderState, targetCopy, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SubmitDepthOnlyTranslatedDraw(IGuestCompiledShader pixelShader,
|
||||||
|
IReadOnlyList<GuestDrawTexture> textures, IReadOnlyList<GuestMemoryBuffer> globalMemoryBuffers,
|
||||||
|
uint attributeCount, GuestDepthTarget depthTarget, IGuestCompiledShader? vertexShader = null,
|
||||||
|
uint vertexCount = 3, uint instanceCount = 1, uint primitiveType = 4,
|
||||||
|
GuestIndexBuffer? indexBuffer = null, IReadOnlyList<GuestVertexBuffer>? vertexBuffers = null,
|
||||||
|
GuestRenderState? renderState = null, ulong shaderAddress = 0)
|
||||||
|
{
|
||||||
|
EnsureStarted(depthTarget.Width, depthTarget.Height);
|
||||||
|
var ps = Spirv(pixelShader); var vs = vertexShader is null ? null : Spirv(vertexShader);
|
||||||
|
var textureCopy = textures.ToArray(); var memoryCopy = globalMemoryBuffers.ToArray();
|
||||||
|
var vertexCopy = vertexBuffers?.ToArray();
|
||||||
|
Enqueue(handle => Check(handle, NativeGpuPacket.SubmitDraw(handle, ps, textureCopy, memoryCopy,
|
||||||
|
depthTarget.Width, depthTarget.Height, attributeCount, vs, vertexCount, instanceCount,
|
||||||
|
primitiveType, indexBuffer, vertexCopy, renderState, null, false)));
|
||||||
|
}
|
||||||
|
|
||||||
public void SubmitStorageTranslatedDraw(IGuestCompiledShader pixelShader,
|
public void SubmitStorageTranslatedDraw(IGuestCompiledShader pixelShader,
|
||||||
IReadOnlyList<GuestDrawTexture> textures, IReadOnlyList<GuestMemoryBuffer> globalMemoryBuffers,
|
IReadOnlyList<GuestDrawTexture> textures, IReadOnlyList<GuestMemoryBuffer> globalMemoryBuffers,
|
||||||
uint attributeCount, uint width, uint height)
|
uint attributeCount, uint width, uint height, ulong shaderAddress = 0)
|
||||||
{
|
{
|
||||||
EnsureStarted(width, height); var ps = Spirv(pixelShader);
|
EnsureStarted(width, height); var ps = Spirv(pixelShader);
|
||||||
var textureCopy = textures.ToArray(); var memoryCopy = globalMemoryBuffers.ToArray();
|
var textureCopy = textures.ToArray(); var memoryCopy = globalMemoryBuffers.ToArray();
|
||||||
@@ -141,14 +169,18 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
|
|||||||
width, height, attributeCount, null, 3, 1, 4, null, null, null, targets, false)));
|
width, height, attributeCount, null, 3, 1, 4, null, null, null, targets, false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SubmitComputeDispatch(ulong shaderAddress, IGuestCompiledShader computeShader,
|
public long SubmitComputeDispatch(ulong shaderAddress, IGuestCompiledShader computeShader,
|
||||||
IReadOnlyList<GuestDrawTexture> textures, IReadOnlyList<GuestMemoryBuffer> globalMemoryBuffers,
|
IReadOnlyList<GuestDrawTexture> textures, IReadOnlyList<GuestMemoryBuffer> globalMemoryBuffers,
|
||||||
uint groupCountX, uint groupCountY, uint groupCountZ)
|
uint groupCountX, uint groupCountY, uint groupCountZ, uint baseGroupX, uint baseGroupY,
|
||||||
|
uint baseGroupZ, uint localSizeX, uint localSizeY, uint localSizeZ, bool isIndirect,
|
||||||
|
bool writesGlobalMemory, uint threadCountX = uint.MaxValue, uint threadCountY = uint.MaxValue,
|
||||||
|
uint threadCountZ = uint.MaxValue)
|
||||||
{
|
{
|
||||||
EnsureStarted(1280, 720); var shader = Spirv(computeShader);
|
EnsureStarted(1280, 720); var shader = Spirv(computeShader);
|
||||||
var textureCopy = textures.ToArray(); var memoryCopy = globalMemoryBuffers.ToArray();
|
var textureCopy = textures.ToArray(); var memoryCopy = globalMemoryBuffers.ToArray();
|
||||||
Enqueue(handle => Check(handle, NativeGpuPacket.SubmitCompute(handle, shaderAddress, shader,
|
Enqueue(handle => Check(handle, NativeGpuPacket.SubmitCompute(handle, shaderAddress, shader,
|
||||||
textureCopy, memoryCopy, groupCountX, groupCountY, groupCountZ)));
|
textureCopy, memoryCopy, groupCountX, groupCountY, groupCountZ)));
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TrySubmitGuestImage(ulong address, uint width, uint height, uint pitchInPixel)
|
public bool TrySubmitGuestImage(ulong address, uint width, uint height, uint pitchInPixel)
|
||||||
@@ -158,6 +190,10 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
|
|||||||
NativeGpuResult.Success;
|
NativeGpuResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TrySubmitOrderedGuestImageFlip(int videoOutHandle, int displayBufferIndex, ulong address,
|
||||||
|
uint width, uint height, uint pitchInPixel) =>
|
||||||
|
TrySubmitGuestImage(address, width, height, pitchInPixel);
|
||||||
|
|
||||||
public void RegisterKnownDisplayBuffer(ulong address, uint guestFormat)
|
public void RegisterKnownDisplayBuffer(ulong address, uint guestFormat)
|
||||||
{
|
{
|
||||||
EnsureStarted(1280, 720);
|
EnsureStarted(1280, 720);
|
||||||
@@ -172,8 +208,8 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bool TrySubmitGuestImageBlit(ulong sourceAddress, uint sourceWidth, uint sourceHeight,
|
public bool TrySubmitGuestImageBlit(ulong sourceAddress, uint sourceWidth, uint sourceHeight,
|
||||||
uint sourceFormat, ulong destinationAddress, uint destinationWidth, uint destinationHeight,
|
uint sourceFormat, uint sourceNumberType, ulong destinationAddress, uint destinationWidth,
|
||||||
uint destinationFormat)
|
uint destinationHeight, uint destinationFormat, uint destinationNumberType)
|
||||||
{
|
{
|
||||||
EnsureStarted(destinationWidth, destinationHeight);
|
EnsureStarted(destinationWidth, destinationHeight);
|
||||||
return Invoke(handle => NativeVulkanApi.BlitGuestImage(handle, sourceAddress, sourceWidth, sourceHeight,
|
return Invoke(handle => NativeVulkanApi.BlitGuestImage(handle, sourceAddress, sourceWidth, sourceHeight,
|
||||||
|
|||||||
Reference in New Issue
Block a user