Compare commits

...

4 Commits

Author SHA1 Message Date
riperiperi
1ca0517c99 Vulkan: Fix some issues with CacheByRange (#3743)
* Fix some issues with CacheByRange

- Cache now clears under more circumstances, the most important being the fast path write.
- Cache supports partial clear which should help when more buffers join.
- Fixed an issue with I8->I16 conversion where it wouldn't register the buffer for use on dispose.

Should hopefully fix issues with https://github.com/Ryujinx/Ryujinx-Games-List/issues/4010 and maybe others.

* Fix collection modified exception

* Fix accidental use of parameterless constructor

* Replay DynamicState when restoring from helper shader
2022-10-08 11:28:27 -03:00
gdkchan
599d485bff Change NvMap ID allocation to match nvservices (#3741)
* Change NvMap ID allocation to match nvservices

* Move NvMapIdDictionary to Types
2022-10-05 17:49:18 -03:00
gdkchan
60e16c15b6 Fix memory corruption in BCAT and FS Read methods when buffer is larger than needed (#3739)
* Fix memory corruption in FS Read methods when buffer is larger than needed

* PR feedback

* nit: Don't move this around
2022-10-04 20:12:54 -03:00
gdkchan
2068445939 Fix shader SULD (bindless) instruction using wrong register as handle (#3732)
* GLSL: Do not generate scale helpers if we have no textures

* Fix shader SULD (bindless) instruction using wrong register as handle
2022-10-03 20:40:22 -03:00
22 changed files with 268 additions and 134 deletions

View File

@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2; private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 3728; private const uint CodeGenVersion = 3732;
private const string SharedTocFileName = "shared.toc"; private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data"; private const string SharedDataFileName = "shared.data";

View File

@@ -257,7 +257,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
DeclareSupportUniformBlock(context, context.Config.Stage, scaleElements); DeclareSupportUniformBlock(context, context.Config.Stage, scaleElements);
if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling)) if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling) && scaleElements != 0)
{ {
AppendHelperFunction(context, $"Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_{stage}.glsl"); AppendHelperFunction(context, $"Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_{stage}.glsl");
context.AppendLine(); context.AppendLine();

View File

@@ -279,16 +279,16 @@ namespace Ryujinx.Graphics.Shader.Decoders
Add("1110101110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomB2, InstEmit.SuatomB2, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); Add("1110101110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomB2, InstEmit.SuatomB2, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
Add("1110101011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCasB, InstEmit.SuatomCasB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.SPd); Add("1110101011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCasB, InstEmit.SuatomCasB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.SPd);
Add("1110101x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCas, InstEmit.SuatomCas, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.SPd); Add("1110101x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCas, InstEmit.SuatomCas, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.SPd);
Add("111010110001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldDB, InstEmit.SuldDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB); Add("1110101100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldDB, InstEmit.SuldDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB);
Add("1110101100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldD, InstEmit.SuldD, InstProps.Rd | InstProps.Ra | InstProps.SPd | InstProps.Tex); Add("1110101100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldD, InstEmit.SuldD, InstProps.Rd | InstProps.Ra | InstProps.SPd | InstProps.Tex);
Add("11101011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldB, InstEmit.SuldB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB); Add("1110101100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldB, InstEmit.SuldB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB);
Add("11101011000x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Suld, InstEmit.Suld, InstProps.Rd | InstProps.Ra | InstProps.SPd | InstProps.Tex); Add("1110101100001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Suld, InstEmit.Suld, InstProps.Rd | InstProps.Ra | InstProps.SPd | InstProps.Tex);
Add("111010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuredB, InstEmit.SuredB, InstProps.Rd | InstProps.Ra | InstProps.Rc); Add("1110101101010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuredB, InstEmit.SuredB, InstProps.Rd | InstProps.Ra | InstProps.Rc);
Add("1110101101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sured, InstEmit.Sured, InstProps.Rd | InstProps.Ra); Add("1110101101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sured, InstEmit.Sured, InstProps.Rd | InstProps.Ra);
Add("111010110011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustDB, InstEmit.SustDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB); Add("1110101100110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustDB, InstEmit.SustDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB);
Add("1110101100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustD, InstEmit.SustD, InstProps.Rd | InstProps.Ra | InstProps.Tex); Add("1110101100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustD, InstEmit.SustD, InstProps.Rd | InstProps.Ra | InstProps.Tex);
Add("11101011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustB, InstEmit.SustB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB); Add("1110101100100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustB, InstEmit.SustB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB);
Add("11101011001x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sust, InstEmit.Sust, InstProps.Rd | InstProps.Ra | InstProps.Tex); Add("1110101100101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sust, InstEmit.Sust, InstProps.Rd | InstProps.Ra | InstProps.Tex);
Add("1111000011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sync, InstEmit.Sync, InstProps.Bra); Add("1111000011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sync, InstEmit.Sync, InstProps.Bra);
Add("11000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tex, InstEmit.Tex, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex); Add("11000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tex, InstEmit.Tex, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex);
Add("1101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TexB, InstEmit.TexB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.TexB); Add("1101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TexB, InstEmit.TexB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.TexB);

View File

@@ -123,7 +123,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
InstSuldB op = context.GetOp<InstSuldB>(); InstSuldB op = context.GetOp<InstSuldB>();
EmitSuld(context, op.CacheOp, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: true); EmitSuld(context, op.CacheOp, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, op.SrcC, useComponents: true, false, isBindless: true);
} }
public static void Suld(EmitterContext context) public static void Suld(EmitterContext context)

View File

@@ -109,12 +109,34 @@ namespace Ryujinx.Graphics.Vulkan
{ {
if (isWrite) if (isWrite)
{ {
_cachedConvertedBuffers.Clear(); SignalWrite(0, Size);
} }
return _buffer; return _buffer;
} }
public Auto<DisposableBuffer> GetBuffer(CommandBuffer commandBuffer, int offset, int size, bool isWrite = false)
{
if (isWrite)
{
SignalWrite(offset, size);
}
return _buffer;
}
public void SignalWrite(int offset, int size)
{
if (offset == 0 && size == Size)
{
_cachedConvertedBuffers.Clear();
}
else
{
_cachedConvertedBuffers.ClearRange(offset, size);
}
}
public BufferHandle GetHandle() public BufferHandle GetHandle()
{ {
var handle = _bufferHandle; var handle = _bufferHandle;
@@ -183,6 +205,8 @@ namespace Ryujinx.Graphics.Vulkan
data.Slice(0, dataSize).CopyTo(new Span<byte>((void*)(_map + offset), dataSize)); data.Slice(0, dataSize).CopyTo(new Span<byte>((void*)(_map + offset), dataSize));
SignalWrite(offset, dataSize);
return; return;
} }
} }
@@ -240,7 +264,7 @@ namespace Ryujinx.Graphics.Vulkan
endRenderPass?.Invoke(); endRenderPass?.Invoke();
var dstBuffer = GetBuffer(cbs.CommandBuffer, true).Get(cbs, dstOffset, data.Length).Value; var dstBuffer = GetBuffer(cbs.CommandBuffer, dstOffset, data.Length, true).Get(cbs, dstOffset, data.Length).Value;
InsertBufferBarrier( InsertBufferBarrier(
_gd, _gd,
@@ -364,7 +388,7 @@ namespace Ryujinx.Graphics.Vulkan
public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, int offset, int size) public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, int offset, int size)
{ {
var key = new I8ToI16CacheKey(); var key = new I8ToI16CacheKey(_gd);
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder)) if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
{ {
@@ -373,6 +397,8 @@ namespace Ryujinx.Graphics.Vulkan
_gd.PipelineInternal.EndRenderPass(); _gd.PipelineInternal.EndRenderPass();
_gd.HelperShader.ConvertI8ToI16(_gd, cbs, this, holder, offset, size); _gd.HelperShader.ConvertI8ToI16(_gd, cbs, this, holder, offset, size);
key.SetBuffer(holder.GetBuffer());
_cachedConvertedBuffers.Add(offset, size, key, holder); _cachedConvertedBuffers.Add(offset, size, key, holder);
} }
@@ -417,6 +443,8 @@ namespace Ryujinx.Graphics.Vulkan
_gd.PipelineInternal.EndRenderPass(); _gd.PipelineInternal.EndRenderPass();
_gd.HelperShader.ConvertIndexBuffer(_gd, cbs, this, holder, pattern, indexSize, offset, indexCount); _gd.HelperShader.ConvertIndexBuffer(_gd, cbs, this, holder, pattern, indexSize, offset, indexCount);
key.SetBuffer(holder.GetBuffer());
_cachedConvertedBuffers.Add(offset, size, key, holder); _cachedConvertedBuffers.Add(offset, size, key, holder);
} }

View File

@@ -124,6 +124,16 @@ namespace Ryujinx.Graphics.Vulkan
return null; return null;
} }
public Auto<DisposableBuffer> GetBuffer(CommandBuffer commandBuffer, BufferHandle handle, int offset, int size, bool isWrite)
{
if (TryGetBuffer(handle, out var holder))
{
return holder.GetBuffer(commandBuffer, offset, size, isWrite);
}
return null;
}
public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, BufferHandle handle, int offset, int size) public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, BufferHandle handle, int offset, int size)
{ {
if (TryGetBuffer(handle, out var holder)) if (TryGetBuffer(handle, out var holder))

View File

@@ -25,6 +25,11 @@ namespace Ryujinx.Graphics.Vulkan
return other is I8ToI16CacheKey; return other is I8ToI16CacheKey;
} }
public void SetBuffer(Auto<DisposableBuffer> buffer)
{
_buffer = buffer;
}
public void Dispose() public void Dispose()
{ {
_gd.PipelineInternal.DirtyIndexBuffer(_buffer); _gd.PipelineInternal.DirtyIndexBuffer(_buffer);
@@ -160,6 +165,44 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
public void ClearRange(int offset, int size)
{
if (_ranges != null && _ranges.Count > 0)
{
int end = offset + size;
List<ulong> toRemove = null;
foreach (KeyValuePair<ulong, List<Entry>> range in _ranges)
{
(int rOffset, int rSize) = UnpackRange(range.Key);
int rEnd = rOffset + rSize;
if (rEnd > offset && rOffset < end)
{
List<Entry> entries = range.Value;
foreach (Entry entry in entries)
{
entry.Key.Dispose();
entry.Value.Dispose();
}
(toRemove ??= new List<ulong>()).Add(range.Key);
}
}
if (toRemove != null)
{
foreach (ulong range in toRemove)
{
_ranges.Remove(range);
}
}
}
}
private List<Entry> GetEntries(int offset, int size) private List<Entry> GetEntries(int offset, int size)
{ {
if (_ranges == null) if (_ranges == null)
@@ -184,6 +227,11 @@ namespace Ryujinx.Graphics.Vulkan
return (uint)offset | ((ulong)size << 32); return (uint)offset | ((ulong)size << 32);
} }
private static (int offset, int size) UnpackRange(ulong range)
{
return ((int)range, (int)(range >> 32));
}
public void Dispose() public void Dispose()
{ {
Clear(); Clear();

View File

@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
protected readonly AutoFlushCounter AutoFlush; protected readonly AutoFlushCounter AutoFlush;
private PipelineDynamicState _dynamicState; protected PipelineDynamicState DynamicState;
private PipelineState _newState; private PipelineState _newState;
private bool _stateDirty; private bool _stateDirty;
private GAL.PrimitiveTopology _topology; private GAL.PrimitiveTopology _topology;
@@ -150,7 +150,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
EndRenderPass(); EndRenderPass();
var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, true).Get(Cbs, offset, size).Value; var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, offset, size, true).Get(Cbs, offset, size).Value;
BufferHolder.InsertBufferBarrier( BufferHolder.InsertBufferBarrier(
Gd, Gd,
@@ -238,8 +238,8 @@ namespace Ryujinx.Graphics.Vulkan
{ {
EndRenderPass(); EndRenderPass();
var src = Gd.BufferManager.GetBuffer(CommandBuffer, source, false); var src = Gd.BufferManager.GetBuffer(CommandBuffer, source, srcOffset, size, false);
var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, true); var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, dstOffset, size, true);
BufferHolder.Copy(Gd, Cbs, src, dst, srcOffset, dstOffset, size); BufferHolder.Copy(Gd, Cbs, src, dst, srcOffset, dstOffset, size);
} }
@@ -388,7 +388,7 @@ namespace Ryujinx.Graphics.Vulkan
var oldDepthTestEnable = _newState.DepthTestEnable; var oldDepthTestEnable = _newState.DepthTestEnable;
var oldDepthWriteEnable = _newState.DepthWriteEnable; var oldDepthWriteEnable = _newState.DepthWriteEnable;
var oldTopology = _newState.Topology; var oldTopology = _newState.Topology;
var oldViewports = _dynamicState.Viewports; var oldViewports = DynamicState.Viewports;
var oldViewportsCount = _newState.ViewportsCount; var oldViewportsCount = _newState.ViewportsCount;
_newState.CullMode = CullModeFlags.CullModeNone; _newState.CullMode = CullModeFlags.CullModeNone;
@@ -411,9 +411,9 @@ namespace Ryujinx.Graphics.Vulkan
_newState.DepthWriteEnable = oldDepthWriteEnable; _newState.DepthWriteEnable = oldDepthWriteEnable;
_newState.Topology = oldTopology; _newState.Topology = oldTopology;
_dynamicState.Viewports = oldViewports; DynamicState.Viewports = oldViewports;
_dynamicState.ViewportsCount = (int)oldViewportsCount; DynamicState.ViewportsCount = (int)oldViewportsCount;
_dynamicState.SetViewportsDirty(); DynamicState.SetViewportsDirty();
_newState.ViewportsCount = oldViewportsCount; _newState.ViewportsCount = oldViewportsCount;
SignalStateChange(); SignalStateChange();
@@ -448,8 +448,13 @@ namespace Ryujinx.Graphics.Vulkan
ResumeTransformFeedbackInternal(); ResumeTransformFeedbackInternal();
DrawCount++; DrawCount++;
var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, indirectBuffer.Handle, true).Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; var buffer = Gd.BufferManager
var countBuffer = Gd.BufferManager.GetBuffer(CommandBuffer, parameterBuffer.Handle, true).Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value; .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, true)
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
var countBuffer = Gd.BufferManager
.GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
.Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
Gd.DrawIndirectCountApi.CmdDrawIndirectCount( Gd.DrawIndirectCountApi.CmdDrawIndirectCount(
CommandBuffer, CommandBuffer,
@@ -478,8 +483,13 @@ namespace Ryujinx.Graphics.Vulkan
ResumeTransformFeedbackInternal(); ResumeTransformFeedbackInternal();
DrawCount++; DrawCount++;
var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, indirectBuffer.Handle, true).Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; var buffer = Gd.BufferManager
var countBuffer = Gd.BufferManager.GetBuffer(CommandBuffer, parameterBuffer.Handle, true).Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value; .GetBuffer(CommandBuffer, indirectBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
.Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
var countBuffer = Gd.BufferManager
.GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
.Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount( Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount(
CommandBuffer, CommandBuffer,
@@ -535,7 +545,7 @@ namespace Ryujinx.Graphics.Vulkan
public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
{ {
_dynamicState.SetDepthBias(factor, units, clamp); DynamicState.SetDepthBias(factor, units, clamp);
_newState.DepthBiasEnable = enables != 0; _newState.DepthBiasEnable = enables != 0;
SignalStateChange(); SignalStateChange();
@@ -753,10 +763,10 @@ namespace Ryujinx.Graphics.Vulkan
var offset = new Offset2D(region.X, region.Y); var offset = new Offset2D(region.X, region.Y);
var extent = new Extent2D((uint)region.Width, (uint)region.Height); var extent = new Extent2D((uint)region.Width, (uint)region.Height);
_dynamicState.SetScissor(i, new Rect2D(offset, extent)); DynamicState.SetScissor(i, new Rect2D(offset, extent));
} }
_dynamicState.ScissorsCount = count; DynamicState.ScissorsCount = count;
_newState.ScissorsCount = (uint)count; _newState.ScissorsCount = (uint)count;
SignalStateChange(); SignalStateChange();
@@ -764,7 +774,7 @@ namespace Ryujinx.Graphics.Vulkan
public void SetStencilTest(StencilTestDescriptor stencilTest) public void SetStencilTest(StencilTestDescriptor stencilTest)
{ {
_dynamicState.SetStencilMasks( DynamicState.SetStencilMasks(
(uint)stencilTest.BackFuncMask, (uint)stencilTest.BackFuncMask,
(uint)stencilTest.BackMask, (uint)stencilTest.BackMask,
(uint)stencilTest.BackFuncRef, (uint)stencilTest.BackFuncRef,
@@ -813,7 +823,8 @@ namespace Ryujinx.Graphics.Vulkan
if (range.Handle != BufferHandle.Null) if (range.Handle != BufferHandle.Null)
{ {
_transformFeedbackBuffers[i] = new BufferState(Gd.BufferManager.GetBuffer(CommandBuffer, range.Handle, true), range.Offset, range.Size); _transformFeedbackBuffers[i] =
new BufferState(Gd.BufferManager.GetBuffer(CommandBuffer, range.Handle, range.Offset, range.Size, true), range.Offset, range.Size);
_transformFeedbackBuffers[i].BindTransformFeedbackBuffer(Gd, Cbs, (uint)i); _transformFeedbackBuffers[i].BindTransformFeedbackBuffer(Gd, Cbs, (uint)i);
} }
else else
@@ -975,7 +986,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
var viewport = viewports[i]; var viewport = viewports[i];
_dynamicState.SetViewport(i, new Silk.NET.Vulkan.Viewport( DynamicState.SetViewport(i, new Silk.NET.Vulkan.Viewport(
viewport.Region.X, viewport.Region.X,
viewport.Region.Y, viewport.Region.Y,
viewport.Region.Width == 0f ? 1f : viewport.Region.Width, viewport.Region.Width == 0f ? 1f : viewport.Region.Width,
@@ -984,7 +995,7 @@ namespace Ryujinx.Graphics.Vulkan
Clamp(viewport.DepthFar))); Clamp(viewport.DepthFar)));
} }
_dynamicState.ViewportsCount = count; DynamicState.ViewportsCount = count;
float disableTransformF = disableTransform ? 1.0f : 0.0f; float disableTransformF = disableTransform ? 1.0f : 0.0f;
if (SupportBufferUpdater.Data.ViewportInverse.W != disableTransformF || disableTransform) if (SupportBufferUpdater.Data.ViewportInverse.W != disableTransformF || disableTransform)
@@ -1063,7 +1074,7 @@ namespace Ryujinx.Graphics.Vulkan
_vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length); _vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length);
_descriptorSetUpdater.SignalCommandBufferChange(); _descriptorSetUpdater.SignalCommandBufferChange();
_dynamicState.ForceAllDirty(); DynamicState.ForceAllDirty();
_currentPipelineHandle = 0; _currentPipelineHandle = 0;
} }
@@ -1201,7 +1212,7 @@ namespace Ryujinx.Graphics.Vulkan
private void RecreatePipelineIfNeeded(PipelineBindPoint pbp) private void RecreatePipelineIfNeeded(PipelineBindPoint pbp)
{ {
_dynamicState.ReplayIfDirty(Gd.Api, CommandBuffer); DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
// Commit changes to the support buffer before drawing. // Commit changes to the support buffer before drawing.
SupportBufferUpdater.Commit(); SupportBufferUpdater.Commit();

View File

@@ -204,6 +204,8 @@ namespace Ryujinx.Graphics.Vulkan
} }
SignalCommandBufferChange(); SignalCommandBufferChange();
DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
} }
public void FlushCommandsImpl() public void FlushCommandsImpl()

View File

@@ -87,7 +87,7 @@ namespace Ryujinx.Graphics.Vulkan
private void PushDataImpl(CommandBufferScoped cbs, BufferHolder dst, int dstOffset, ReadOnlySpan<byte> data) private void PushDataImpl(CommandBufferScoped cbs, BufferHolder dst, int dstOffset, ReadOnlySpan<byte> data)
{ {
var srcBuffer = _buffer.GetBuffer(); var srcBuffer = _buffer.GetBuffer();
var dstBuffer = dst.GetBuffer(); var dstBuffer = dst.GetBuffer(cbs.CommandBuffer, dstOffset, data.Length, true);
int offset = _freeOffset; int offset = _freeOffset;
int capacity = BufferSize - offset; int capacity = BufferSize - offset;

View File

@@ -38,18 +38,17 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
// Read() -> (u32, buffer<nn::bcat::DeliveryCacheDirectoryEntry, 6>) // Read() -> (u32, buffer<nn::bcat::DeliveryCacheDirectoryEntry, 6>)
public ResultCode Read(ServiceCtx context) public ResultCode Read(ServiceCtx context)
{ {
ulong position = context.Request.ReceiveBuff[0].Position; ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
ulong size = context.Request.ReceiveBuff[0].Size; ulong bufferLen = context.Request.ReceiveBuff[0].Size;
byte[] data = new byte[size]; using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
{
Result result = _base.Get.Read(out int entriesRead, MemoryMarshal.Cast<byte, DeliveryCacheDirectoryEntry>(region.Memory.Span));
Result result = _base.Get.Read(out int entriesRead, MemoryMarshal.Cast<byte, DeliveryCacheDirectoryEntry>(data)); context.ResponseData.Write(entriesRead);
context.Memory.Write(position, data); return (ResultCode)result.Value;
}
context.ResponseData.Write(entriesRead);
return (ResultCode)result.Value;
} }
[CommandHipc(2)] [CommandHipc(2)]

View File

@@ -38,20 +38,19 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
// Read(u64) -> (u64, buffer<bytes, 6>) // Read(u64) -> (u64, buffer<bytes, 6>)
public ResultCode Read(ServiceCtx context) public ResultCode Read(ServiceCtx context)
{ {
ulong position = context.Request.ReceiveBuff[0].Position; ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
ulong size = context.Request.ReceiveBuff[0].Size; ulong bufferLen = context.Request.ReceiveBuff[0].Size;
long offset = context.RequestData.ReadInt64(); long offset = context.RequestData.ReadInt64();
byte[] data = new byte[size]; using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
{
Result result = _base.Get.Read(out long bytesRead, offset, region.Memory.Span);
Result result = _base.Get.Read(out long bytesRead, offset, data); context.ResponseData.Write(bytesRead);
context.Memory.Write(position, data); return (ResultCode)result.Value;
}
context.ResponseData.Write(bytesRead);
return (ResultCode)result.Value;
} }
[CommandHipc(2)] [CommandHipc(2)]

View File

@@ -50,18 +50,17 @@ namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator
// EnumerateDeliveryCacheDirectory() -> (u32, buffer<nn::bcat::DirectoryName, 6>) // EnumerateDeliveryCacheDirectory() -> (u32, buffer<nn::bcat::DirectoryName, 6>)
public ResultCode EnumerateDeliveryCacheDirectory(ServiceCtx context) public ResultCode EnumerateDeliveryCacheDirectory(ServiceCtx context)
{ {
ulong position = context.Request.ReceiveBuff[0].Position; ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
ulong size = context.Request.ReceiveBuff[0].Size; ulong bufferLen = context.Request.ReceiveBuff[0].Size;
byte[] data = new byte[size]; using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
{
Result result = _base.Get.EnumerateDeliveryCacheDirectory(out int count, MemoryMarshal.Cast<byte, DirectoryName>(region.Memory.Span));
Result result = _base.Get.EnumerateDeliveryCacheDirectory(out int count, MemoryMarshal.Cast<byte, DirectoryName>(data)); context.ResponseData.Write(count);
context.Memory.Write(position, data); return (ResultCode)result.Value;
}
context.ResponseData.Write(count);
return (ResultCode)result.Value;
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@@ -17,17 +17,17 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
// Read() -> (u64 count, buffer<nn::fssrv::sf::IDirectoryEntry, 6, 0> entries) // Read() -> (u64 count, buffer<nn::fssrv::sf::IDirectoryEntry, 6, 0> entries)
public ResultCode Read(ServiceCtx context) public ResultCode Read(ServiceCtx context)
{ {
ulong bufferPosition = context.Request.ReceiveBuff[0].Position; ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
ulong bufferLen = context.Request.ReceiveBuff[0].Size; ulong bufferLen = context.Request.ReceiveBuff[0].Size;
byte[] entryBuffer = new byte[bufferLen]; using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
{
Result result = _baseDirectory.Get.Read(out long entriesRead, new OutBuffer(region.Memory.Span));
Result result = _baseDirectory.Get.Read(out long entriesRead, new OutBuffer(entryBuffer)); context.ResponseData.Write(entriesRead);
context.Memory.Write(bufferPosition, entryBuffer); return (ResultCode)result.Value;
context.ResponseData.Write(entriesRead); }
return (ResultCode)result.Value;
} }
[CommandHipc(1)] [CommandHipc(1)]

View File

@@ -19,7 +19,8 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
// Read(u32 readOption, u64 offset, u64 size) -> (u64 out_size, buffer<u8, 0x46, 0> out_buf) // Read(u32 readOption, u64 offset, u64 size) -> (u64 out_size, buffer<u8, 0x46, 0> out_buf)
public ResultCode Read(ServiceCtx context) public ResultCode Read(ServiceCtx context)
{ {
ulong position = context.Request.ReceiveBuff[0].Position; ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
ulong bufferLen = context.Request.ReceiveBuff[0].Size;
ReadOption readOption = context.RequestData.ReadStruct<ReadOption>(); ReadOption readOption = context.RequestData.ReadStruct<ReadOption>();
context.RequestData.BaseStream.Position += 4; context.RequestData.BaseStream.Position += 4;
@@ -27,15 +28,14 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
long offset = context.RequestData.ReadInt64(); long offset = context.RequestData.ReadInt64();
long size = context.RequestData.ReadInt64(); long size = context.RequestData.ReadInt64();
byte[] data = new byte[context.Request.ReceiveBuff[0].Size]; using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
{
Result result = _baseFile.Get.Read(out long bytesRead, offset, new OutBuffer(region.Memory.Span), size, readOption);
Result result = _baseFile.Get.Read(out long bytesRead, offset, new OutBuffer(data), size, readOption); context.ResponseData.Write(bytesRead);
context.Memory.Write(position, data); return (ResultCode)result.Value;
}
context.ResponseData.Write(bytesRead);
return (ResultCode)result.Value;
} }
[CommandHipc(1)] [CommandHipc(1)]

View File

@@ -197,13 +197,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
context.ResponseData.Write(timestamp.Created); context.ResponseData.Write(timestamp.Created);
context.ResponseData.Write(timestamp.Modified); context.ResponseData.Write(timestamp.Modified);
context.ResponseData.Write(timestamp.Accessed); context.ResponseData.Write(timestamp.Accessed);
context.ResponseData.Write(1L); // Is valid?
byte[] data = new byte[8];
// is valid?
data[0] = 1;
context.ResponseData.Write(data);
return (ResultCode)result.Value; return (ResultCode)result.Value;
} }

View File

@@ -23,21 +23,21 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
if (context.Request.ReceiveBuff.Count > 0) if (context.Request.ReceiveBuff.Count > 0)
{ {
IpcBuffDesc buffDesc = context.Request.ReceiveBuff[0]; ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
ulong bufferLen = context.Request.ReceiveBuff[0].Size;
// Use smaller length to avoid overflows. // Use smaller length to avoid overflows.
if (size > buffDesc.Size) if (size > bufferLen)
{ {
size = buffDesc.Size; size = bufferLen;
} }
byte[] data = new byte[size]; using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
{
Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size);
Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(data), (long)size); return (ResultCode)result.Value;
}
context.Memory.Write(buffDesc.Position, data);
return (ResultCode)result.Value;
} }
return ResultCode.Success; return ResultCode.Success;

View File

@@ -500,16 +500,16 @@ namespace Ryujinx.HLE.HOS.Services.Fs
SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64(); SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64();
SaveDataFilter filter = context.RequestData.ReadStruct<SaveDataFilter>(); SaveDataFilter filter = context.RequestData.ReadStruct<SaveDataFilter>();
ulong bufferPosition = context.Request.ReceiveBuff[0].Position; ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
ulong bufferLen = context.Request.ReceiveBuff[0].Size; ulong bufferLen = context.Request.ReceiveBuff[0].Size;
byte[] infoBuffer = new byte[bufferLen]; using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
{
Result result = _baseFileSystemProxy.Get.FindSaveDataWithFilter(out long count, new OutBuffer(region.Memory.Span), spaceId, in filter);
if (result.IsFailure()) return (ResultCode)result.Value;
Result result = _baseFileSystemProxy.Get.FindSaveDataWithFilter(out long count, new OutBuffer(infoBuffer), spaceId, in filter); context.ResponseData.Write(count);
if (result.IsFailure()) return (ResultCode)result.Value; }
context.Memory.Write(bufferPosition, infoBuffer);
context.ResponseData.Write(count);
return ResultCode.Success; return ResultCode.Success;
} }

View File

@@ -17,17 +17,17 @@ namespace Ryujinx.HLE.HOS.Services.Fs
// ReadSaveDataInfo() -> (u64, buffer<unknown, 6>) // ReadSaveDataInfo() -> (u64, buffer<unknown, 6>)
public ResultCode ReadSaveDataInfo(ServiceCtx context) public ResultCode ReadSaveDataInfo(ServiceCtx context)
{ {
ulong bufferPosition = context.Request.ReceiveBuff[0].Position; ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
ulong bufferLen = context.Request.ReceiveBuff[0].Size; ulong bufferLen = context.Request.ReceiveBuff[0].Size;
byte[] infoBuffer = new byte[bufferLen]; using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
{
Result result = _baseReader.Get.Read(out long readCount, new OutBuffer(region.Memory.Span));
Result result = _baseReader.Get.Read(out long readCount, new OutBuffer(infoBuffer)); context.ResponseData.Write(readCount);
context.Memory.Write(bufferPosition, infoBuffer); return (ResultCode)result.Value;
context.ResponseData.Write(readCount); }
return (ResultCode)result.Value;
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@@ -3,7 +3,6 @@ using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
using System.Collections.Concurrent;
namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
{ {
@@ -11,13 +10,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
{ {
private const int FlagNotFreedYet = 1; private const int FlagNotFreedYet = 1;
private static ConcurrentDictionary<ulong, IdDictionary> _maps = new ConcurrentDictionary<ulong, IdDictionary>(); private static NvMapIdDictionary _maps = new NvMapIdDictionary();
public NvMapDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner) public NvMapDeviceFile(ServiceCtx context, IVirtualMemoryManager memory, ulong owner) : base(context, owner)
{ {
IdDictionary dict = _maps.GetOrAdd(Owner, (key) => new IdDictionary());
dict.Add(0, new NvMapHandle());
} }
public override NvInternalResult Ioctl(NvIoctl command, Span<byte> arguments) public override NvInternalResult Ioctl(NvIoctl command, Span<byte> arguments)
@@ -232,19 +228,12 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
private int CreateHandleFromMap(NvMapHandle map) private int CreateHandleFromMap(NvMapHandle map)
{ {
IdDictionary dict = _maps.GetOrAdd(Owner, (key) => new IdDictionary()); return _maps.Add(map);
return dict.Add(map);
} }
private static bool DeleteMapWithHandle(ulong pid, int handle) private static bool DeleteMapWithHandle(ulong pid, int handle)
{ {
if (_maps.TryGetValue(pid, out IdDictionary dict)) return _maps.Delete(handle) != null;
{
return dict.Delete(handle) != null;
}
return false;
} }
public static void IncrementMapRefCount(ulong pid, int handle) public static void IncrementMapRefCount(ulong pid, int handle)
@@ -277,12 +266,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
public static NvMapHandle GetMapFromHandle(ulong pid, int handle) public static NvMapHandle GetMapFromHandle(ulong pid, int handle)
{ {
if (_maps.TryGetValue(pid, out IdDictionary dict)) return _maps.Get(handle);
{
return dict.GetData<NvMapHandle>(handle);
}
return null;
} }
} }
} }

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap
{
class NvMapIdDictionary
{
private readonly ConcurrentDictionary<int, NvMapHandle> _nvmapHandles;
private int _id;
public ICollection<NvMapHandle> Values => _nvmapHandles.Values;
public NvMapIdDictionary()
{
_nvmapHandles = new ConcurrentDictionary<int, NvMapHandle>();
}
public int Add(NvMapHandle handle)
{
int id = Interlocked.Add(ref _id, 4);
if (id != 0 && _nvmapHandles.TryAdd(id, handle))
{
return id;
}
throw new InvalidOperationException("NvMap ID overflow.");
}
public NvMapHandle Get(int id)
{
if (_nvmapHandles.TryGetValue(id, out NvMapHandle handle))
{
return handle;
}
return null;
}
public NvMapHandle Delete(int id)
{
if (_nvmapHandles.TryRemove(id, out NvMapHandle handle))
{
return handle;
}
return null;
}
public ICollection<NvMapHandle> Clear()
{
ICollection<NvMapHandle> values = _nvmapHandles.Values;
_nvmapHandles.Clear();
return values;
}
}
}

View File

@@ -142,14 +142,13 @@ namespace Ryujinx.HLE.HOS.Services.Ssl.SslService
// GetHostName(buffer<bytes, 6>) -> u32 // GetHostName(buffer<bytes, 6>) -> u32
public ResultCode GetHostName(ServiceCtx context) public ResultCode GetHostName(ServiceCtx context)
{ {
ulong hostNameDataPosition = context.Request.ReceiveBuff[0].Position; ulong bufferAddress = context.Request.ReceiveBuff[0].Position;
ulong hostNameDataSize = context.Request.ReceiveBuff[0].Size; ulong bufferLen = context.Request.ReceiveBuff[0].Size;
byte[] hostNameData = new byte[hostNameDataSize]; using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true))
{
Encoding.ASCII.GetBytes(_hostName, hostNameData); Encoding.ASCII.GetBytes(_hostName, region.Memory.Span);
}
context.Memory.Write(hostNameDataPosition, hostNameData);
context.ResponseData.Write((uint)_hostName.Length); context.ResponseData.Write((uint)_hostName.Length);