mirror of
https://git.ryujinx.app/projects/Kenji-NX.git
synced 2026-09-23 23:50:07 +02:00
Android changes
This commit is contained in:
@@ -130,9 +130,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
UsePushDescriptors = usePushDescriptors;
|
||||
|
||||
Stages = stages;
|
||||
bool hasBatchedTextureSamplerBug = false;//gd.Vendor == Vendor.Qualcomm;
|
||||
|
||||
ClearSegments = BuildClearSegments(sets);
|
||||
BindingSegments = BuildBindingSegments(resourceLayout.SetUsages, out bool usesBufferTextures);
|
||||
BindingSegments = BuildBindingSegments(resourceLayout.SetUsages, hasBatchedTextureSamplerBug, out bool usesBufferTextures);
|
||||
Templates = BuildTemplates(usePushDescriptors);
|
||||
(IncoherentBufferWriteStages, IncoherentTextureWriteStages) = BuildIncoherentStages(resourceLayout.SetUsages);
|
||||
|
||||
@@ -168,7 +169,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
// If binding 3 is immediately used, use an alternate set of reserved bindings.
|
||||
ReadOnlyCollection<ResourceUsage> uniformUsage = layout.SetUsages[0].Usages;
|
||||
bool hasBinding3 = uniformUsage.Any(x => x.Binding == 3);
|
||||
int[] reserved = isCompute ? [] : gd.GetPushDescriptorReservedBindings(hasBinding3);
|
||||
int[] reserved = isCompute ? Array.Empty<int>() : gd.GetPushDescriptorReservedBindings(hasBinding3);
|
||||
|
||||
// Can't use any of the reserved usages.
|
||||
for (int i = 0; i < uniformUsage.Count; i++)
|
||||
@@ -182,16 +183,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Prevent the sum of descriptors from exceeding MaxPushDescriptors
|
||||
int totalDescriptors = 0;
|
||||
foreach (ResourceDescriptor desc in layout.Sets.First().Descriptors)
|
||||
{
|
||||
if (!reserved.Contains(desc.Binding))
|
||||
totalDescriptors += desc.Count;
|
||||
}
|
||||
if (totalDescriptors > gd.Capabilities.MaxPushDescriptors)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -249,7 +240,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
for (int setIndex = 0; setIndex < sets.Count; setIndex++)
|
||||
{
|
||||
List<ResourceBindingSegment> currentSegments = [];
|
||||
List<ResourceBindingSegment> currentSegments = new();
|
||||
|
||||
ResourceDescriptor currentDescriptor = default;
|
||||
int currentCount = 0;
|
||||
@@ -299,7 +290,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return segments;
|
||||
}
|
||||
|
||||
private static ResourceBindingSegment[][] BuildBindingSegments(ReadOnlyCollection<ResourceUsageCollection> setUsages, out bool usesBufferTextures)
|
||||
private static ResourceBindingSegment[][] BuildBindingSegments(ReadOnlyCollection<ResourceUsageCollection> setUsages, bool hasBatchedTextureBug, out bool usesBufferTextures)
|
||||
{
|
||||
usesBufferTextures = false;
|
||||
|
||||
@@ -307,7 +298,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
for (int setIndex = 0; setIndex < setUsages.Count; setIndex++)
|
||||
{
|
||||
List<ResourceBindingSegment> currentSegments = [];
|
||||
List<ResourceBindingSegment> currentSegments = new();
|
||||
|
||||
ResourceUsage currentUsage = default;
|
||||
int currentCount = 0;
|
||||
@@ -323,6 +314,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
if (currentUsage.Binding + currentCount != usage.Binding ||
|
||||
currentUsage.Type != usage.Type ||
|
||||
(IsReadOnlyTexture(currentUsage.Type) && hasBatchedTextureBug) ||
|
||||
currentUsage.Stages != usage.Stages ||
|
||||
currentUsage.ArrayLength > 1 ||
|
||||
usage.ArrayLength > 1)
|
||||
@@ -458,6 +450,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return (buffer, texture);
|
||||
}
|
||||
|
||||
private static bool IsReadOnlyTexture(ResourceType resourceType)
|
||||
{
|
||||
return resourceType == ResourceType.TextureAndSampler || resourceType == ResourceType.BufferTexture;
|
||||
|
||||
}
|
||||
|
||||
private async Task BackgroundCompilation()
|
||||
{
|
||||
await Task.WhenAll(_shaders.Select(shader => shader.CompileTask));
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples);
|
||||
|
||||
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities);
|
||||
var usage = GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, true);
|
||||
|
||||
var flags = ImageCreateFlags.CreateMutableFormatBit | ImageCreateFlags.CreateExtendedUsageBit;
|
||||
|
||||
@@ -307,7 +307,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
}
|
||||
}
|
||||
|
||||
public static ImageUsageFlags GetImageUsage(Format format, Target target, in HardwareCapabilities capabilities)
|
||||
public static ImageUsageFlags GetImageUsage(Format format, in HardwareCapabilities capabilities, bool isMsImageStorageSupported, bool extendedUsage)
|
||||
{
|
||||
var usage = DefaultUsageFlags;
|
||||
|
||||
@@ -320,19 +320,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
usage |= ImageUsageFlags.ColorAttachmentBit;
|
||||
}
|
||||
|
||||
bool isMsImageStorageSupported = capabilities.SupportsShaderStorageImageMultisample;
|
||||
|
||||
if (format.IsImageCompatible() && (isMsImageStorageSupported || !target.IsMultisample()))
|
||||
if ((format.IsImageCompatible() && isMsImageStorageSupported) || extendedUsage)
|
||||
{
|
||||
usage |= ImageUsageFlags.StorageBit;
|
||||
}
|
||||
|
||||
if (capabilities.SupportsAttachmentFeedbackLoop &&
|
||||
(usage & (ImageUsageFlags.DepthStencilAttachmentBit | ImageUsageFlags.ColorAttachmentBit)) != 0)
|
||||
{
|
||||
usage |= ImageUsageFlags.AttachmentFeedbackLoopBitExt;
|
||||
}
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
bool isMsImageStorageSupported = gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample();
|
||||
|
||||
var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format, isMsImageStorageSupported);
|
||||
var usage = TextureStorage.GetImageUsage(info.Format, info.Target, gd.Capabilities);
|
||||
var usage = TextureStorage.GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, false);
|
||||
|
||||
var levels = (uint)info.Levels;
|
||||
var layers = (uint)info.GetLayers();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Silk.NET.Core;
|
||||
using Silk.NET.Vulkan;
|
||||
using Silk.NET.Vulkan.Extensions.EXT;
|
||||
using System;
|
||||
@@ -16,6 +17,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private readonly ExtDebugUtils _debugUtils;
|
||||
private readonly DebugUtilsMessengerEXT? _debugUtilsMessenger;
|
||||
private bool _disposed;
|
||||
private unsafe delegate* unmanaged[Cdecl]<DebugUtilsMessageSeverityFlagsEXT, DebugUtilsMessageTypeFlagsEXT, DebugUtilsMessengerCallbackDataEXT*, void*, Bool32> _messageDelegate;
|
||||
|
||||
public VulkanDebugMessenger(Vk api, Instance instance, GraphicsDebugLevel logLevel)
|
||||
{
|
||||
@@ -71,7 +73,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
unsafe
|
||||
{
|
||||
debugUtilsMessengerCreateInfo.PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(UserCallback);
|
||||
_messageDelegate = (delegate* unmanaged[Cdecl]<DebugUtilsMessageSeverityFlagsEXT, DebugUtilsMessageTypeFlagsEXT, DebugUtilsMessengerCallbackDataEXT*, void*, Bool32>)Marshal.GetFunctionPointerForDelegate(UserCallback);
|
||||
debugUtilsMessengerCreateInfo.PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(_messageDelegate);
|
||||
}
|
||||
|
||||
DebugUtilsMessengerEXT messengerHandle = default;
|
||||
@@ -89,7 +92,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private unsafe static uint UserCallback(
|
||||
private unsafe static Bool32 UserCallback(
|
||||
DebugUtilsMessageSeverityFlagsEXT messageSeverity,
|
||||
DebugUtilsMessageTypeFlagsEXT messageTypes,
|
||||
DebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||
|
||||
@@ -77,6 +77,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public IWindow Window => _window;
|
||||
|
||||
public SurfaceTransformFlagsKHR CurrentTransform => _window.CurrentTransform;
|
||||
|
||||
private readonly Func<Instance, Vk, SurfaceKHR> _getSurface;
|
||||
private readonly Func<string[]> _getRequiredExtensions;
|
||||
private readonly string _preferredGpuId;
|
||||
@@ -1008,6 +1010,15 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
return !(IsMoltenVk || IsQualcommProprietary);
|
||||
}
|
||||
|
||||
internal unsafe void RecreateSurface()
|
||||
{
|
||||
SurfaceApi.DestroySurface(_instance.Instance, _surface, null);
|
||||
|
||||
_surface = _getSurface(_instance.Instance, Api);
|
||||
|
||||
(_window as Window)?.SetSurface(_surface);
|
||||
}
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (!_initialized)
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
private const int SurfaceHeight = 720;
|
||||
|
||||
private readonly VulkanRenderer _gd;
|
||||
private readonly SurfaceKHR _surface;
|
||||
private readonly PhysicalDevice _physicalDevice;
|
||||
private readonly Device _device;
|
||||
private SurfaceKHR _surface;
|
||||
private SwapchainKHR _swapchain;
|
||||
|
||||
private Image[] _swapchainImages;
|
||||
@@ -84,6 +84,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
CreateSwapchain();
|
||||
}
|
||||
|
||||
internal void SetSurface(SurfaceKHR surface)
|
||||
{
|
||||
_surface = surface;
|
||||
RecreateSwapchain();
|
||||
}
|
||||
|
||||
private unsafe void CreateSwapchain()
|
||||
{
|
||||
_gd.SurfaceApi.GetPhysicalDeviceSurfaceCapabilities(_physicalDevice, _surface, out var capabilities);
|
||||
@@ -126,6 +132,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
var oldSwapchain = _swapchain;
|
||||
|
||||
CurrentTransform = capabilities.CurrentTransform;
|
||||
|
||||
var swapchainCreateInfo = new SwapchainCreateInfoKHR
|
||||
{
|
||||
SType = StructureType.SwapchainCreateInfoKhr,
|
||||
@@ -134,10 +142,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
ImageFormat = surfaceFormat.Format,
|
||||
ImageColorSpace = surfaceFormat.ColorSpace,
|
||||
ImageExtent = extent,
|
||||
ImageUsage = ImageUsageFlags.ColorAttachmentBit | ImageUsageFlags.TransferDstBit | ImageUsageFlags.StorageBit,
|
||||
ImageUsage = ImageUsageFlags.ColorAttachmentBit | ImageUsageFlags.TransferDstBit | (Ryujinx.Common.PlatformInfo.IsBionic ? 0 : ImageUsageFlags.StorageBit),
|
||||
ImageSharingMode = SharingMode.Exclusive,
|
||||
ImageArrayLayers = 1,
|
||||
PreTransform = capabilities.CurrentTransform,
|
||||
PreTransform = Ryujinx.Common.PlatformInfo.IsBionic ? SurfaceTransformFlagsKHR.IdentityBitKhr : capabilities.CurrentTransform,
|
||||
CompositeAlpha = ChooseCompositeAlpha(capabilities.SupportedCompositeAlpha),
|
||||
PresentMode = ChooseSwapPresentMode(presentModes, _vSyncMode),
|
||||
Clipped = true,
|
||||
@@ -332,6 +340,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
RecreateSwapchain();
|
||||
semaphoreIndex = (_frameIndex - 1) % _imageAvailableSemaphores.Length;
|
||||
}
|
||||
else if(acquireResult == Result.ErrorSurfaceLostKhr)
|
||||
{
|
||||
_gd.RecreateSurface();
|
||||
}
|
||||
else
|
||||
{
|
||||
acquireResult.ThrowOnError();
|
||||
@@ -393,7 +405,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
_gd.CommandBufferPool.Return(
|
||||
cbs,
|
||||
null,
|
||||
[PipelineStageFlags.ColorAttachmentOutputBit],
|
||||
stackalloc[] { PipelineStageFlags.ColorAttachmentOutputBit },
|
||||
null);
|
||||
_gd.FlushAllCommands();
|
||||
cbs.GetFence().Wait();
|
||||
@@ -456,9 +468,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
_gd.CommandBufferPool.Return(
|
||||
cbs,
|
||||
[_imageAvailableSemaphores[semaphoreIndex]],
|
||||
[PipelineStageFlags.ColorAttachmentOutputBit],
|
||||
[_renderFinishedSemaphores[semaphoreIndex]]);
|
||||
stackalloc[] { _imageAvailableSemaphores[semaphoreIndex] },
|
||||
stackalloc[] { PipelineStageFlags.ColorAttachmentOutputBit },
|
||||
stackalloc[] { _renderFinishedSemaphores[semaphoreIndex] });
|
||||
|
||||
// TODO: Present queue.
|
||||
var semaphore = _renderFinishedSemaphores[semaphoreIndex];
|
||||
@@ -481,6 +493,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
_gd.SwapchainApi.QueuePresent(_gd.Queue, in presentInfo);
|
||||
}
|
||||
|
||||
//While this does nothing in most cases, it's useful to notify the end of the frame, and is used to handle native window in Android.
|
||||
swapBuffersCallback?.Invoke();
|
||||
}
|
||||
|
||||
public override void SetAntiAliasing(AntiAliasing effect)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
@@ -6,6 +7,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
internal abstract class WindowBase : IWindow
|
||||
{
|
||||
public bool ScreenCaptureRequested { get; set; }
|
||||
|
||||
public SurfaceTransformFlagsKHR CurrentTransform { get; set; }
|
||||
|
||||
public abstract void Dispose();
|
||||
public abstract void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback);
|
||||
|
||||
Reference in New Issue
Block a user