Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9719b6a112 | ||
|
f70236f947 | ||
|
eafadf10c7 | ||
|
9b06ee7736 |
10
.github/workflows/nightly_pr_comment.yml
vendored
10
.github/workflows/nightly_pr_comment.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
const pull_head_sha = '${{github.event.workflow_run.head_sha}}';
|
const pull_head_sha = '${{github.event.workflow_run.head_sha}}';
|
||||||
|
|
||||||
const issue_number = await (async () => {
|
const issue_number = await (async () => {
|
||||||
const pulls = await github.pulls.list({owner, repo});
|
const pulls = await github.rest.pulls.list({owner, repo});
|
||||||
for await (const {data} of github.paginate.iterator(pulls)) {
|
for await (const {data} of github.paginate.iterator(pulls)) {
|
||||||
for (const pull of data) {
|
for (const pull of data) {
|
||||||
if (pull.head.sha === pull_head_sha) {
|
if (pull.head.sha === pull_head_sha) {
|
||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
return core.error(`No matching pull request found`);
|
return core.error(`No matching pull request found`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const {data: {artifacts}} = await github.actions.listWorkflowRunArtifacts({owner, repo, run_id});
|
const {data: {artifacts}} = await github.rest.actions.listWorkflowRunArtifacts({owner, repo, run_id});
|
||||||
if (!artifacts.length) {
|
if (!artifacts.length) {
|
||||||
return core.error(`No artifacts found`);
|
return core.error(`No artifacts found`);
|
||||||
}
|
}
|
||||||
@@ -57,12 +57,12 @@ jobs:
|
|||||||
body += hidden_headless_artifacts;
|
body += hidden_headless_artifacts;
|
||||||
body += hidden_debug_artifacts;
|
body += hidden_debug_artifacts;
|
||||||
|
|
||||||
const {data: comments} = await github.issues.listComments({repo, owner, issue_number});
|
const {data: comments} = await github.rest.issues.listComments({repo, owner, issue_number});
|
||||||
const existing_comment = comments.find((c) => c.user.login === 'github-actions[bot]');
|
const existing_comment = comments.find((c) => c.user.login === 'github-actions[bot]');
|
||||||
if (existing_comment) {
|
if (existing_comment) {
|
||||||
core.info(`Updating comment ${existing_comment.id}`);
|
core.info(`Updating comment ${existing_comment.id}`);
|
||||||
await github.issues.updateComment({repo, owner, comment_id: existing_comment.id, body});
|
await github.rest.issues.updateComment({repo, owner, comment_id: existing_comment.id, body});
|
||||||
} else {
|
} else {
|
||||||
core.info(`Creating a comment`);
|
core.info(`Creating a comment`);
|
||||||
await github.issues.createComment({repo, owner, issue_number, body});
|
await github.rest.issues.createComment({repo, owner, issue_number, body});
|
||||||
}
|
}
|
||||||
|
@@ -36,8 +36,8 @@
|
|||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
As of October 2022, Ryujinx has been tested on approximately 3,600 titles; over 3,500 boot past menus and into gameplay, with roughly 3,000 of those being considered playable. You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues).
|
As of October 2022, Ryujinx has been tested on approximately 3,700 titles; over 3,500 boot past menus and into gameplay, with roughly 3,000 of those being considered playable.
|
||||||
Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues). Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ Ryujinx system files are stored in the `Ryujinx` folder. This folder is located
|
|||||||
|
|
||||||
- **GPU**
|
- **GPU**
|
||||||
|
|
||||||
The GPU emulator emulates the Switch's Maxwell GPU using the OpenGL API (version 4.5 minimum) through a custom build of OpenTK. There are currently four graphics enhancements available to the end user in Ryujinx: disk shader caching, resolution scaling, aspect ratio adjustment and anisotropic filtering. These enhancements can be adjusted or toggled as desired in the GUI.
|
The GPU emulator emulates the Switch's Maxwell GPU using either the OpenGL (version 4.5 minimum) or Vulkan APIs through a custom build of OpenTK or Silk.NET respectively. There are currently four graphics enhancements available to the end user in Ryujinx: Disk Shader Caching, Resolution Scaling, Aspect Ratio Adjustment, and Anisotropic Filtering. These enhancements can be adjusted or toggled as desired in the GUI.
|
||||||
|
|
||||||
- **Input**
|
- **Input**
|
||||||
|
|
||||||
|
@@ -535,10 +535,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
vkBlend = new PipelineColorBlendAttachmentState();
|
vkBlend = new PipelineColorBlendAttachmentState();
|
||||||
}
|
}
|
||||||
|
|
||||||
_newState.BlendConstantR = blend.BlendConstant.Red;
|
DynamicState.SetBlendConstants(
|
||||||
_newState.BlendConstantG = blend.BlendConstant.Green;
|
blend.BlendConstant.Red,
|
||||||
_newState.BlendConstantB = blend.BlendConstant.Blue;
|
blend.BlendConstant.Green,
|
||||||
_newState.BlendConstantA = blend.BlendConstant.Alpha;
|
blend.BlendConstant.Blue,
|
||||||
|
blend.BlendConstant.Alpha);
|
||||||
|
|
||||||
SignalStateChange();
|
SignalStateChange();
|
||||||
}
|
}
|
||||||
|
@@ -135,11 +135,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
// It is assumed that Dynamic State is enabled when this conversion is used.
|
// It is assumed that Dynamic State is enabled when this conversion is used.
|
||||||
|
|
||||||
pipeline.BlendConstantA = state.BlendDescriptors[0].BlendConstant.Alpha;
|
|
||||||
pipeline.BlendConstantB = state.BlendDescriptors[0].BlendConstant.Blue;
|
|
||||||
pipeline.BlendConstantG = state.BlendDescriptors[0].BlendConstant.Green;
|
|
||||||
pipeline.BlendConstantR = state.BlendDescriptors[0].BlendConstant.Red;
|
|
||||||
|
|
||||||
pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.CullModeNone;
|
pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.CullModeNone;
|
||||||
|
|
||||||
pipeline.DepthBoundsTestEnable = false; // Not implemented.
|
pipeline.DepthBoundsTestEnable = false; // Not implemented.
|
||||||
|
@@ -19,21 +19,34 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private uint _frontWriteMask;
|
private uint _frontWriteMask;
|
||||||
private uint _frontReference;
|
private uint _frontReference;
|
||||||
|
|
||||||
|
private Array4<float> _blendConstants;
|
||||||
|
|
||||||
public int ViewportsCount;
|
public int ViewportsCount;
|
||||||
public Array16<Viewport> Viewports;
|
public Array16<Viewport> Viewports;
|
||||||
|
|
||||||
private enum DirtyFlags
|
private enum DirtyFlags
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
DepthBias = 1 << 0,
|
Blend = 1 << 0,
|
||||||
Scissor = 1 << 1,
|
DepthBias = 1 << 1,
|
||||||
Stencil = 1 << 2,
|
Scissor = 1 << 2,
|
||||||
Viewport = 1 << 3,
|
Stencil = 1 << 3,
|
||||||
All = DepthBias | Scissor | Stencil | Viewport
|
Viewport = 1 << 4,
|
||||||
|
All = Blend | DepthBias | Scissor | Stencil | Viewport
|
||||||
}
|
}
|
||||||
|
|
||||||
private DirtyFlags _dirty;
|
private DirtyFlags _dirty;
|
||||||
|
|
||||||
|
public void SetBlendConstants(float r, float g, float b, float a)
|
||||||
|
{
|
||||||
|
_blendConstants[0] = r;
|
||||||
|
_blendConstants[1] = g;
|
||||||
|
_blendConstants[2] = b;
|
||||||
|
_blendConstants[3] = a;
|
||||||
|
|
||||||
|
_dirty |= DirtyFlags.Blend;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetDepthBias(float slopeFactor, float constantFactor, float clamp)
|
public void SetDepthBias(float slopeFactor, float constantFactor, float clamp)
|
||||||
{
|
{
|
||||||
_depthBiasSlopeFactor = slopeFactor;
|
_depthBiasSlopeFactor = slopeFactor;
|
||||||
@@ -87,6 +100,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void ReplayIfDirty(Vk api, CommandBuffer commandBuffer)
|
public void ReplayIfDirty(Vk api, CommandBuffer commandBuffer)
|
||||||
{
|
{
|
||||||
|
if (_dirty.HasFlag(DirtyFlags.Blend))
|
||||||
|
{
|
||||||
|
RecordBlend(api, commandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.DepthBias))
|
if (_dirty.HasFlag(DirtyFlags.DepthBias))
|
||||||
{
|
{
|
||||||
RecordDepthBias(api, commandBuffer);
|
RecordDepthBias(api, commandBuffer);
|
||||||
@@ -110,6 +128,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_dirty = DirtyFlags.None;
|
_dirty = DirtyFlags.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RecordBlend(Vk api, CommandBuffer commandBuffer)
|
||||||
|
{
|
||||||
|
api.CmdSetBlendConstants(commandBuffer, _blendConstants.AsSpan());
|
||||||
|
}
|
||||||
|
|
||||||
private void RecordDepthBias(Vk api, CommandBuffer commandBuffer)
|
private void RecordDepthBias(Vk api, CommandBuffer commandBuffer)
|
||||||
{
|
{
|
||||||
api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor);
|
api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor);
|
||||||
|
@@ -499,7 +499,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
colorBlendState.BlendConstants[3] = BlendConstantA;
|
colorBlendState.BlendConstants[3] = BlendConstantA;
|
||||||
|
|
||||||
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
||||||
int dynamicStatesCount = supportsExtDynamicState ? 8 : 7;
|
int dynamicStatesCount = supportsExtDynamicState ? 9 : 8;
|
||||||
|
|
||||||
DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
|
DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
|
||||||
|
|
||||||
@@ -510,10 +510,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
dynamicStates[4] = DynamicState.StencilCompareMask;
|
dynamicStates[4] = DynamicState.StencilCompareMask;
|
||||||
dynamicStates[5] = DynamicState.StencilWriteMask;
|
dynamicStates[5] = DynamicState.StencilWriteMask;
|
||||||
dynamicStates[6] = DynamicState.StencilReference;
|
dynamicStates[6] = DynamicState.StencilReference;
|
||||||
|
dynamicStates[7] = DynamicState.BlendConstants;
|
||||||
|
|
||||||
if (supportsExtDynamicState)
|
if (supportsExtDynamicState)
|
||||||
{
|
{
|
||||||
dynamicStates[7] = DynamicState.VertexInputBindingStrideExt;
|
dynamicStates[8] = DynamicState.VertexInputBindingStrideExt;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo()
|
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo()
|
||||||
|
@@ -3,9 +3,10 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Tests.Unicorn
|
namespace Ryujinx.Tests.Unicorn
|
||||||
{
|
{
|
||||||
public class UnicornAArch32
|
public class UnicornAArch32 : IDisposable
|
||||||
{
|
{
|
||||||
internal readonly IntPtr uc;
|
internal readonly IntPtr uc;
|
||||||
|
private bool _isDisposed = false;
|
||||||
|
|
||||||
public IndexedProperty<int, uint> R
|
public IndexedProperty<int, uint> R
|
||||||
{
|
{
|
||||||
@@ -107,7 +108,22 @@ namespace Ryujinx.Tests.Unicorn
|
|||||||
|
|
||||||
~UnicornAArch32()
|
~UnicornAArch32()
|
||||||
{
|
{
|
||||||
Interface.Checked(Native.Interface.uc_close(uc));
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!_isDisposed)
|
||||||
|
{
|
||||||
|
Interface.Checked(Native.Interface.uc_close(uc));
|
||||||
|
_isDisposed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RunForCount(ulong count)
|
public void RunForCount(ulong count)
|
||||||
|
@@ -3,9 +3,10 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Tests.Unicorn
|
namespace Ryujinx.Tests.Unicorn
|
||||||
{
|
{
|
||||||
public class UnicornAArch64
|
public class UnicornAArch64 : IDisposable
|
||||||
{
|
{
|
||||||
internal readonly IntPtr uc;
|
internal readonly IntPtr uc;
|
||||||
|
private bool _isDisposed = false;
|
||||||
|
|
||||||
public IndexedProperty<int, ulong> X
|
public IndexedProperty<int, ulong> X
|
||||||
{
|
{
|
||||||
@@ -96,7 +97,22 @@ namespace Ryujinx.Tests.Unicorn
|
|||||||
|
|
||||||
~UnicornAArch64()
|
~UnicornAArch64()
|
||||||
{
|
{
|
||||||
Interface.Checked(Native.Interface.uc_close(uc));
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!_isDisposed)
|
||||||
|
{
|
||||||
|
Interface.Checked(Native.Interface.uc_close(uc));
|
||||||
|
_isDisposed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RunForCount(ulong count)
|
public void RunForCount(ulong count)
|
||||||
|
@@ -80,6 +80,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
[TearDown]
|
[TearDown]
|
||||||
public void Teardown()
|
public void Teardown()
|
||||||
{
|
{
|
||||||
|
if (_unicornAvailable)
|
||||||
|
{
|
||||||
|
_unicornEmu.Dispose();
|
||||||
|
_unicornEmu = null;
|
||||||
|
}
|
||||||
|
|
||||||
_memory.DecrementReferenceCount();
|
_memory.DecrementReferenceCount();
|
||||||
_context.Dispose();
|
_context.Dispose();
|
||||||
_ram.Dispose();
|
_ram.Dispose();
|
||||||
|
@@ -76,6 +76,12 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
[TearDown]
|
[TearDown]
|
||||||
public void Teardown()
|
public void Teardown()
|
||||||
{
|
{
|
||||||
|
if (_unicornAvailable)
|
||||||
|
{
|
||||||
|
_unicornEmu.Dispose();
|
||||||
|
_unicornEmu = null;
|
||||||
|
}
|
||||||
|
|
||||||
_memory.DecrementReferenceCount();
|
_memory.DecrementReferenceCount();
|
||||||
_context.Dispose();
|
_context.Dispose();
|
||||||
_ram.Dispose();
|
_ram.Dispose();
|
||||||
|
Reference in New Issue
Block a user