diff --git a/src/SharpEmu.Libs/Gpu/NativeVulkan/NativeVulkanGuestGpuBackend.cs b/src/SharpEmu.Libs/Gpu/NativeVulkan/NativeVulkanGuestGpuBackend.cs
index 7141e51f..17f5c2a0 100644
--- a/src/SharpEmu.Libs/Gpu/NativeVulkan/NativeVulkanGuestGpuBackend.cs
+++ b/src/SharpEmu.Libs/Gpu/NativeVulkan/NativeVulkanGuestGpuBackend.cs
@@ -12,6 +12,9 @@ namespace SharpEmu.Libs.Gpu.NativeVulkan;
/// Native C++ Vulkan implementation of the guest-domain GPU seam.
internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
{
+ private static readonly IGuestCompiledShader DepthOnlyFragmentShader =
+ new VulkanCompiledGuestShader(SpirvFixedShaders.CreateDepthOnlyFragment());
+
private readonly object _startGate = new();
private readonly BlockingCollection> _commands = new(new ConcurrentQueue>(), 256);
private readonly ManualResetEventSlim _ready = new(false);
@@ -48,34 +51,43 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
public bool TryCompileVertexShader(Gen5ShaderState state, Gen5ShaderEvaluation evaluation,
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;
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;
}
public bool TryCompilePixelShader(Gen5ShaderState state, Gen5ShaderEvaluation evaluation,
IReadOnlyList outputs, out IGuestCompiledShader? shader, out string error,
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;
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;
}
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;
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;
}
+ public IGuestCompiledShader GetDepthOnlyFragmentShader() => DepthOnlyFragmentShader;
+
public void HideSplashScreen() { }
public void Submit(byte[] bgraFrame, uint width, uint height)
@@ -118,7 +130,7 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
uint attributeCount, IReadOnlyList targets, IGuestCompiledShader? vertexShader = null,
uint vertexCount = 3, uint instanceCount = 1, uint primitiveType = 4,
GuestIndexBuffer? indexBuffer = null, IReadOnlyList? vertexBuffers = null,
- GuestRenderState? renderState = null)
+ GuestRenderState? renderState = null, GuestDepthTarget? depthTarget = null, ulong shaderAddress = 0)
{
if (targets.Count == 0) return;
EnsureStarted(targets[0].Width, targets[0].Height);
@@ -130,9 +142,25 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
primitiveType, indexBuffer, vertexCopy, renderState, targetCopy, true)));
}
+ public void SubmitDepthOnlyTranslatedDraw(IGuestCompiledShader pixelShader,
+ IReadOnlyList textures, IReadOnlyList globalMemoryBuffers,
+ uint attributeCount, GuestDepthTarget depthTarget, IGuestCompiledShader? vertexShader = null,
+ uint vertexCount = 3, uint instanceCount = 1, uint primitiveType = 4,
+ GuestIndexBuffer? indexBuffer = null, IReadOnlyList? 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,
IReadOnlyList textures, IReadOnlyList globalMemoryBuffers,
- uint attributeCount, uint width, uint height)
+ uint attributeCount, uint width, uint height, ulong shaderAddress = 0)
{
EnsureStarted(width, height); var ps = Spirv(pixelShader);
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)));
}
- public void SubmitComputeDispatch(ulong shaderAddress, IGuestCompiledShader computeShader,
+ public long SubmitComputeDispatch(ulong shaderAddress, IGuestCompiledShader computeShader,
IReadOnlyList textures, IReadOnlyList 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);
var textureCopy = textures.ToArray(); var memoryCopy = globalMemoryBuffers.ToArray();
Enqueue(handle => Check(handle, NativeGpuPacket.SubmitCompute(handle, shaderAddress, shader,
textureCopy, memoryCopy, groupCountX, groupCountY, groupCountZ)));
+ return 0;
}
public bool TrySubmitGuestImage(ulong address, uint width, uint height, uint pitchInPixel)
@@ -158,6 +190,10 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
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)
{
EnsureStarted(1280, 720);
@@ -172,8 +208,8 @@ internal sealed unsafe class NativeVulkanGuestGpuBackend : IGuestGpuBackend
}
public bool TrySubmitGuestImageBlit(ulong sourceAddress, uint sourceWidth, uint sourceHeight,
- uint sourceFormat, ulong destinationAddress, uint destinationWidth, uint destinationHeight,
- uint destinationFormat)
+ uint sourceFormat, uint sourceNumberType, ulong destinationAddress, uint destinationWidth,
+ uint destinationHeight, uint destinationFormat, uint destinationNumberType)
{
EnsureStarted(destinationWidth, destinationHeight);
return Invoke(handle => NativeVulkanApi.BlitGuestImage(handle, sourceAddress, sourceWidth, sourceHeight,