Merge branch 'master' into GetPhysicalCoreCount

This commit is contained in:
sunshineinabox 2023-07-14 07:38:39 -07:00 committed by GitHub
commit e8af9144c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
93 changed files with 603 additions and 3269 deletions

View file

@ -1,8 +0,0 @@
addReviewers: true
reviewers:
- marysaka
filterLabels:
include:
- audio

View file

@ -1,11 +0,0 @@
addReviewers: true
reviewers:
- gdkchan
- riperiperi
- marysaka
- LDj3SNuD
filterLabels:
include:
- cpu

View file

@ -1,4 +0,0 @@
addReviewers: true
reviewers:
- Ryujinx/developers

View file

@ -1,10 +0,0 @@
addReviewers: true
reviewers:
- gdkchan
- riperiperi
- marysaka
filterLabels:
include:
- gpu

View file

@ -1,11 +0,0 @@
addReviewers: true
reviewers:
- Ack77
- emmauss
- TSRBerry
- marysaka
filterLabels:
include:
- gui

View file

@ -1,11 +0,0 @@
addReviewers: true
reviewers:
- gdkchan
- Ack77
- marysaka
- TSRBerry
filterLabels:
include:
- horizon

View file

@ -1,9 +0,0 @@
addReviewers: true
reviewers:
- marysaka
- TSRBerry
filterLabels:
include:
- infra

32
.github/reviewers.yml vendored Normal file
View file

@ -0,0 +1,32 @@
audio:
- marysaka
cpu:
- gdkchan
- riperiperi
- marysaka
- LDj3SNuD
gpu:
- gdkchan
- riperiperi
- marysaka
gui:
- Ack77
- emmauss
- TSRBerry
- marysaka
horizon:
- gdkchan
- Ack77
- marysaka
- TSRBerry
infra:
- marysaka
- TSRBerry
default:
- marysaka

79
.github/update_reviewers.py vendored Normal file
View file

@ -0,0 +1,79 @@
from pathlib import Path
from typing import List, Set
from github import Github
from github.Repository import Repository
from github.GithubException import GithubException
import sys
import yaml
def add_reviewers(
reviewers: Set[str], team_reviewers: Set[str], new_entries: List[str]
):
for reviewer in new_entries:
if reviewer.startswith("@"):
team_reviewers.add(reviewer[1:])
else:
reviewers.add(reviewer)
def update_reviewers(config, repo: Repository, pr_id: int) -> int:
pull_request = repo.get_pull(pr_id)
if not pull_request:
sys.stderr.writable(f"Unknown PR #{pr_id}\n")
return 1
pull_request_author = pull_request.user.login
reviewers = set()
team_reviewers = set()
for label in pull_request.labels:
if label.name in config:
add_reviewers(reviewers, team_reviewers, config[label.name])
if "default" in config:
add_reviewers(reviewers, team_reviewers, config["default"])
if pull_request_author in reviewers:
reviewers.remove(pull_request_author)
try:
reviewers = list(reviewers)
team_reviewers = list(team_reviewers)
print(
f"Attempting to assign reviewers ({reviewers}) and team_reviewers ({team_reviewers})"
)
pull_request.create_review_request(reviewers, team_reviewers)
return 0
except GithubException as e:
sys.stderr.write(f"Cannot assign review request for PR #{pr_id}: {e}\n")
return 1
if __name__ == "__main__":
if len(sys.argv) != 5:
sys.stderr.write("usage: <token> <repo_path> <pr_id> <config_path>\n")
sys.exit(1)
token = sys.argv[1]
repo_path = sys.argv[2]
pr_id = int(sys.argv[3])
config_path = Path(sys.argv[4])
g = Github(token)
repo = g.get_repo(repo_path)
if not repo:
sys.stderr.write("Repository not found!\n")
sys.exit(1)
if not config_path.exists():
sys.stderr.write(f'Config "{config_path}" not found!\n')
sys.exit(1)
with open(config_path, "r") as f:
config = yaml.safe_load(f)
sys.exit(update_reviewers(config, repo, pr_id))

View file

@ -12,43 +12,23 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
# Grab sources to get update_reviewers.py and reviewers.yml
- name: Fetch sources
uses: actions/checkout@v3
with:
# Ensure we pin the source origin as pull_request_target run under forks.
fetch-depth: 0
repository: Ryujinx/Ryujinx
ref: master
- name: Update labels based on changes - name: Update labels based on changes
uses: actions/labeler@v4 uses: actions/labeler@v4
with: with:
sync-labels: true sync-labels: true
dot: true dot: true
- name: Auto Assign [Audio] - name: Assign reviewers
uses: kentaro-m/auto-assign-action@v1.2.5 run: |
with: pip3 install PyGithub
configuration-path: '.github/assign/audio.yml' python3 .github/update_reviewers.py ${{ secrets.GITHUB_TOKEN }} ${{ github.repository }} ${{ github.event.pull_request.number }} .github/reviewers.yml
shell: bash
- name: Auto Assign [CPU]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/cpu.yml'
- name: Auto Assign [GPU]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/gpu.yml'
- name: Auto Assign [GUI]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/gui.yml'
- name: Auto Assign [Horizon]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/horizon.yml'
- name: Auto Assign [Infra]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/infra.yml'
- name: Auto Assign [Global]
uses: kentaro-m/auto-assign-action@v1.2.5
with:
configuration-path: '.github/assign/global.yml'

View file

@ -79,7 +79,6 @@ namespace Ryujinx.Graphics.GAL
void SetRasterizerDiscard(bool discard); void SetRasterizerDiscard(bool discard);
void SetRenderTargetScale(float scale);
void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask); void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask);
void SetRenderTargets(ITexture[] colors, ITexture depthStencil); void SetRenderTargets(ITexture[] colors, ITexture depthStencil);
@ -99,7 +98,7 @@ namespace Ryujinx.Graphics.GAL
void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs); void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs);
void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers); void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers);
void SetViewports(ReadOnlySpan<Viewport> viewports, bool disableTransform); void SetViewports(ReadOnlySpan<Viewport> viewports);
void TextureBarrier(); void TextureBarrier();
void TextureBarrierTiled(); void TextureBarrierTiled();
@ -107,7 +106,5 @@ namespace Ryujinx.Graphics.GAL
bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual); bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual);
bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual); bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual);
void EndHostConditionalRendering(); void EndHostConditionalRendering();
void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount);
} }
} }

View file

@ -17,7 +17,6 @@ namespace Ryujinx.Graphics.GAL
void BackgroundContextAction(Action action, bool alwaysBackground = false); void BackgroundContextAction(Action action, bool alwaysBackground = false);
BufferHandle CreateBuffer(int size, BufferHandle storageHint); BufferHandle CreateBuffer(int size, BufferHandle storageHint);
BufferHandle CreateBuffer(int size) BufferHandle CreateBuffer(int size)
{ {
return CreateBuffer(size, BufferHandle.Null); return CreateBuffer(size, BufferHandle.Null);
@ -28,7 +27,7 @@ namespace Ryujinx.Graphics.GAL
IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info); IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info);
ISampler CreateSampler(SamplerCreateInfo info); ISampler CreateSampler(SamplerCreateInfo info);
ITexture CreateTexture(TextureCreateInfo info, float scale); ITexture CreateTexture(TextureCreateInfo info);
bool PrepareHostMapping(nint address, ulong size); bool PrepareHostMapping(nint address, ulong size);
void CreateSync(ulong id, bool strict); void CreateSync(ulong id, bool strict);
@ -49,7 +48,7 @@ namespace Ryujinx.Graphics.GAL
void PreFrame(); void PreFrame();
ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, bool hostReserved); ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved);
void ResetCounter(CounterType type); void ResetCounter(CounterType type);

View file

@ -6,7 +6,6 @@ namespace Ryujinx.Graphics.GAL
{ {
int Width { get; } int Width { get; }
int Height { get; } int Height { get; }
float ScaleFactor { get; }
void CopyTo(ITexture destination, int firstLayer, int firstLevel); void CopyTo(ITexture destination, int firstLayer, int firstLevel);
void CopyTo(ITexture destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel); void CopyTo(ITexture destination, int srcLayer, int dstLayer, int srcLevel, int dstLevel);

View file

@ -125,7 +125,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
Register<SetProgramCommand>(CommandType.SetProgram); Register<SetProgramCommand>(CommandType.SetProgram);
Register<SetRasterizerDiscardCommand>(CommandType.SetRasterizerDiscard); Register<SetRasterizerDiscardCommand>(CommandType.SetRasterizerDiscard);
Register<SetRenderTargetColorMasksCommand>(CommandType.SetRenderTargetColorMasks); Register<SetRenderTargetColorMasksCommand>(CommandType.SetRenderTargetColorMasks);
Register<SetRenderTargetScaleCommand>(CommandType.SetRenderTargetScale);
Register<SetRenderTargetsCommand>(CommandType.SetRenderTargets); Register<SetRenderTargetsCommand>(CommandType.SetRenderTargets);
Register<SetScissorsCommand>(CommandType.SetScissor); Register<SetScissorsCommand>(CommandType.SetScissor);
Register<SetStencilTestCommand>(CommandType.SetStencilTest); Register<SetStencilTestCommand>(CommandType.SetStencilTest);
@ -138,7 +137,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
Register<TextureBarrierTiledCommand>(CommandType.TextureBarrierTiled); Register<TextureBarrierTiledCommand>(CommandType.TextureBarrierTiled);
Register<TryHostConditionalRenderingCommand>(CommandType.TryHostConditionalRendering); Register<TryHostConditionalRenderingCommand>(CommandType.TryHostConditionalRendering);
Register<TryHostConditionalRenderingFlushCommand>(CommandType.TryHostConditionalRenderingFlush); Register<TryHostConditionalRenderingFlushCommand>(CommandType.TryHostConditionalRenderingFlush);
Register<UpdateRenderScaleCommand>(CommandType.UpdateRenderScale);
return maxCommandSize; return maxCommandSize;
} }

View file

@ -87,7 +87,6 @@
SetProgram, SetProgram,
SetRasterizerDiscard, SetRasterizerDiscard,
SetRenderTargetColorMasks, SetRenderTargetColorMasks,
SetRenderTargetScale,
SetRenderTargets, SetRenderTargets,
SetScissor, SetScissor,
SetStencilTest, SetStencilTest,
@ -100,6 +99,5 @@
TextureBarrierTiled, TextureBarrierTiled,
TryHostConditionalRendering, TryHostConditionalRendering,
TryHostConditionalRenderingFlush, TryHostConditionalRenderingFlush,
UpdateRenderScale,
} }
} }

View file

@ -8,18 +8,16 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
public readonly CommandType CommandType => CommandType.CreateTexture; public readonly CommandType CommandType => CommandType.CreateTexture;
private TableRef<ThreadedTexture> _texture; private TableRef<ThreadedTexture> _texture;
private TextureCreateInfo _info; private TextureCreateInfo _info;
private float _scale;
public void Set(TableRef<ThreadedTexture> texture, TextureCreateInfo info, float scale) public void Set(TableRef<ThreadedTexture> texture, TextureCreateInfo info)
{ {
_texture = texture; _texture = texture;
_info = info; _info = info;
_scale = scale;
} }
public static void Run(ref CreateTextureCommand command, ThreadedRenderer threaded, IRenderer renderer) public static void Run(ref CreateTextureCommand command, ThreadedRenderer threaded, IRenderer renderer)
{ {
command._texture.Get(threaded).Base = renderer.CreateTexture(command._info, command._scale); command._texture.Get(threaded).Base = renderer.CreateTexture(command._info);
} }
} }
} }

View file

@ -10,13 +10,15 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
private TableRef<ThreadedCounterEvent> _event; private TableRef<ThreadedCounterEvent> _event;
private CounterType _type; private CounterType _type;
private TableRef<EventHandler<ulong>> _resultHandler; private TableRef<EventHandler<ulong>> _resultHandler;
private float _divisor;
private bool _hostReserved; private bool _hostReserved;
public void Set(TableRef<ThreadedCounterEvent> evt, CounterType type, TableRef<EventHandler<ulong>> resultHandler, bool hostReserved) public void Set(TableRef<ThreadedCounterEvent> evt, CounterType type, TableRef<EventHandler<ulong>> resultHandler, float divisor, bool hostReserved)
{ {
_event = evt; _event = evt;
_type = type; _type = type;
_resultHandler = resultHandler; _resultHandler = resultHandler;
_divisor = divisor;
_hostReserved = hostReserved; _hostReserved = hostReserved;
} }
@ -24,7 +26,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
{ {
ThreadedCounterEvent evt = command._event.Get(threaded); ThreadedCounterEvent evt = command._event.Get(threaded);
evt.Create(renderer, command._type, command._resultHandler.Get(threaded), command._hostReserved); evt.Create(renderer, command._type, command._resultHandler.Get(threaded), command._divisor, command._hostReserved);
} }
} }
} }

View file

@ -1,18 +0,0 @@
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetRenderTargetScaleCommand : IGALCommand, IGALCommand<SetRenderTargetScaleCommand>
{
public readonly CommandType CommandType => CommandType.SetRenderTargetScale;
private float _scale;
public void Set(float scale)
{
_scale = scale;
}
public static void Run(ref SetRenderTargetScaleCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
renderer.Pipeline.SetRenderTargetScale(command._scale);
}
}
}

View file

@ -7,18 +7,16 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{ {
public readonly CommandType CommandType => CommandType.SetViewports; public readonly CommandType CommandType => CommandType.SetViewports;
private SpanRef<Viewport> _viewports; private SpanRef<Viewport> _viewports;
private bool _disableTransform;
public void Set(SpanRef<Viewport> viewports, bool disableTransform) public void Set(SpanRef<Viewport> viewports)
{ {
_viewports = viewports; _viewports = viewports;
_disableTransform = disableTransform;
} }
public static void Run(ref SetViewportsCommand command, ThreadedRenderer threaded, IRenderer renderer) public static void Run(ref SetViewportsCommand command, ThreadedRenderer threaded, IRenderer renderer)
{ {
ReadOnlySpan<Viewport> viewports = command._viewports.Get(threaded); ReadOnlySpan<Viewport> viewports = command._viewports.Get(threaded);
renderer.Pipeline.SetViewports(viewports, command._disableTransform); renderer.Pipeline.SetViewports(viewports);
command._viewports.Dispose(threaded); command._viewports.Dispose(threaded);
} }
} }

View file

@ -1,25 +0,0 @@
using Ryujinx.Graphics.GAL.Multithreading.Model;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct UpdateRenderScaleCommand : IGALCommand, IGALCommand<UpdateRenderScaleCommand>
{
public readonly CommandType CommandType => CommandType.UpdateRenderScale;
private SpanRef<float> _scales;
private int _totalCount;
private int _fragmentCount;
public void Set(SpanRef<float> scales, int totalCount, int fragmentCount)
{
_scales = scales;
_totalCount = totalCount;
_fragmentCount = fragmentCount;
}
public static void Run(ref UpdateRenderScaleCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
renderer.Pipeline.UpdateRenderScale(command._scales.Get(threaded), command._totalCount, command._fragmentCount);
command._scales.Dispose(threaded);
}
}
}

View file

@ -70,10 +70,10 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
} }
} }
public void Create(IRenderer renderer, CounterType type, System.EventHandler<ulong> eventHandler, bool hostReserved) public void Create(IRenderer renderer, CounterType type, System.EventHandler<ulong> eventHandler, float divisor, bool hostReserved)
{ {
ThreadedHelpers.SpinUntilExchange(ref _createLock, 1, 0); ThreadedHelpers.SpinUntilExchange(ref _createLock, 1, 0);
Base = renderer.ReportCounter(type, eventHandler, hostReserved || _reserved); Base = renderer.ReportCounter(type, eventHandler, divisor, hostReserved || _reserved);
Volatile.Write(ref _createLock, 0); Volatile.Write(ref _createLock, 0);
} }
} }

View file

@ -17,13 +17,10 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
public int Height => _info.Height; public int Height => _info.Height;
public float ScaleFactor { get; } public ThreadedTexture(ThreadedRenderer renderer, TextureCreateInfo info)
public ThreadedTexture(ThreadedRenderer renderer, TextureCreateInfo info, float scale)
{ {
_renderer = renderer; _renderer = renderer;
_info = info; _info = info;
ScaleFactor = scale;
} }
private TableRef<T> Ref<T>(T reference) private TableRef<T> Ref<T>(T reference)
@ -64,7 +61,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel) public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
{ {
ThreadedTexture newTex = new(_renderer, info, ScaleFactor); ThreadedTexture newTex = new(_renderer, info);
_renderer.New<TextureCreateViewCommand>().Set(Ref(this), Ref(newTex), info, firstLayer, firstLevel); _renderer.New<TextureCreateViewCommand>().Set(Ref(this), Ref(newTex), info, firstLayer, firstLevel);
_renderer.QueueCommand(); _renderer.QueueCommand();

View file

@ -261,12 +261,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_renderer.QueueCommand(); _renderer.QueueCommand();
} }
public void SetRenderTargetScale(float scale)
{
_renderer.New<SetRenderTargetScaleCommand>().Set(scale);
_renderer.QueueCommand();
}
public void SetScissors(ReadOnlySpan<Rectangle<int>> scissors) public void SetScissors(ReadOnlySpan<Rectangle<int>> scissors)
{ {
_renderer.New<SetScissorsCommand>().Set(_renderer.CopySpan(scissors)); _renderer.New<SetScissorsCommand>().Set(_renderer.CopySpan(scissors));
@ -321,9 +315,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_renderer.QueueCommand(); _renderer.QueueCommand();
} }
public void SetViewports(ReadOnlySpan<Viewport> viewports, bool disableTransform) public void SetViewports(ReadOnlySpan<Viewport> viewports)
{ {
_renderer.New<SetViewportsCommand>().Set(_renderer.CopySpan(viewports), disableTransform); _renderer.New<SetViewportsCommand>().Set(_renderer.CopySpan(viewports));
_renderer.QueueCommand(); _renderer.QueueCommand();
} }
@ -368,11 +362,5 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_renderer.QueueCommand(); _renderer.QueueCommand();
return false; return false;
} }
public void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount)
{
_renderer.New<UpdateRenderScaleCommand>().Set(_renderer.CopySpan(scales[..totalCount]), totalCount, fragmentCount);
_renderer.QueueCommand();
}
} }
} }

View file

@ -320,21 +320,21 @@ namespace Ryujinx.Graphics.GAL.Multithreading
QueueCommand(); QueueCommand();
} }
public ITexture CreateTexture(TextureCreateInfo info, float scale) public ITexture CreateTexture(TextureCreateInfo info)
{ {
if (IsGpuThread()) if (IsGpuThread())
{ {
var texture = new ThreadedTexture(this, info, scale); var texture = new ThreadedTexture(this, info);
New<CreateTextureCommand>().Set(Ref(texture), info, scale); New<CreateTextureCommand>().Set(Ref(texture), info);
QueueCommand(); QueueCommand();
return texture; return texture;
} }
else else
{ {
var texture = new ThreadedTexture(this, info, scale) var texture = new ThreadedTexture(this, info)
{ {
Base = _baseRenderer.CreateTexture(info, scale), Base = _baseRenderer.CreateTexture(info),
}; };
return texture; return texture;
@ -410,10 +410,10 @@ namespace Ryujinx.Graphics.GAL.Multithreading
QueueCommand(); QueueCommand();
} }
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, bool hostReserved) public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved)
{ {
ThreadedCounterEvent evt = new(this, type, _lastSampleCounterClear); ThreadedCounterEvent evt = new ThreadedCounterEvent(this, type, _lastSampleCounterClear);
New<ReportCounterCommand>().Set(Ref(evt), type, Ref(resultHandler), hostReserved); New<ReportCounterCommand>().Set(Ref(evt), type, Ref(resultHandler), divisor, hostReserved);
QueueCommand(); QueueCommand();
if (type == CounterType.SamplesPassed) if (type == CounterType.SamplesPassed)

View file

@ -1,102 +0,0 @@
using Ryujinx.Graphics.Shader;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.GAL
{
public class SupportBufferUpdater : IDisposable
{
public SupportBuffer Data;
public BufferHandle Handle;
private readonly IRenderer _renderer;
private int _startOffset = -1;
private int _endOffset = -1;
public SupportBufferUpdater(IRenderer renderer)
{
_renderer = renderer;
Handle = renderer.CreateBuffer(SupportBuffer.RequiredSize);
renderer.Pipeline.ClearBuffer(Handle, 0, SupportBuffer.RequiredSize, 0);
}
private void MarkDirty(int startOffset, int byteSize)
{
int endOffset = startOffset + byteSize;
if (_startOffset == -1)
{
_startOffset = startOffset;
_endOffset = endOffset;
}
else
{
if (startOffset < _startOffset)
{
_startOffset = startOffset;
}
if (endOffset > _endOffset)
{
_endOffset = endOffset;
}
}
}
public void UpdateFragmentRenderScaleCount(int count)
{
if (Data.FragmentRenderScaleCount.X != count)
{
Data.FragmentRenderScaleCount.X = count;
MarkDirty(SupportBuffer.FragmentRenderScaleCountOffset, sizeof(int));
}
}
private void UpdateGenericField<T>(int baseOffset, ReadOnlySpan<T> data, Span<T> target, int offset, int count) where T : unmanaged
{
data[..count].CopyTo(target[offset..]);
int elemSize = Unsafe.SizeOf<T>();
MarkDirty(baseOffset + offset * elemSize, count * elemSize);
}
public void UpdateRenderScale(ReadOnlySpan<Vector4<float>> data, int offset, int count)
{
UpdateGenericField(SupportBuffer.GraphicsRenderScaleOffset, data, Data.RenderScale.AsSpan(), offset, count);
}
public void UpdateFragmentIsBgra(ReadOnlySpan<Vector4<int>> data, int offset, int count)
{
UpdateGenericField(SupportBuffer.FragmentIsBgraOffset, data, Data.FragmentIsBgra.AsSpan(), offset, count);
}
public void UpdateViewportInverse(Vector4<float> data)
{
Data.ViewportInverse = data;
MarkDirty(SupportBuffer.ViewportInverseOffset, SupportBuffer.FieldSize);
}
public void Commit()
{
if (_startOffset != -1)
{
ReadOnlySpan<byte> data = MemoryMarshal.Cast<SupportBuffer, byte>(MemoryMarshal.CreateSpan(ref Data, 1));
_renderer.SetBufferData(Handle, _startOffset, data[_startOffset.._endOffset]);
_startOffset = -1;
_endOffset = -1;
}
}
public void Dispose()
{
GC.SuppressFinalize(this);
_renderer.DeleteBuffer(Handle);
}
}
}

View file

@ -177,13 +177,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
resultHandler(null, (ulong)_state.State.SemaphorePayload); resultHandler(null, (ulong)_state.State.SemaphorePayload);
break; break;
case ReportCounterType.SamplesPassed: case ReportCounterType.SamplesPassed:
counter = _context.Renderer.ReportCounter(CounterType.SamplesPassed, resultHandler, false); float scale = _channel.TextureManager.RenderTargetScale;
float divisor = scale * scale;
counter = _context.Renderer.ReportCounter(CounterType.SamplesPassed, resultHandler, divisor, false);
break; break;
case ReportCounterType.PrimitivesGenerated: case ReportCounterType.PrimitivesGenerated:
counter = _context.Renderer.ReportCounter(CounterType.PrimitivesGenerated, resultHandler, false); counter = _context.Renderer.ReportCounter(CounterType.PrimitivesGenerated, resultHandler, 1f, false);
break; break;
case ReportCounterType.TransformFeedbackPrimitivesWritten: case ReportCounterType.TransformFeedbackPrimitivesWritten:
counter = _context.Renderer.ReportCounter(CounterType.TransformFeedbackPrimitivesWritten, resultHandler, false); counter = _context.Renderer.ReportCounter(CounterType.TransformFeedbackPrimitivesWritten, resultHandler, 1f, false);
break; break;
} }

View file

@ -495,6 +495,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
{ {
clipRegionHeight = color.Height / samplesInY; clipRegionHeight = color.Height / samplesInY;
} }
if (!_context.Capabilities.SupportsBgraFormat)
{
_context.SupportBufferUpdater.SetRenderTargetIsBgra(index, color.Format.IsBgr());
}
} }
} }
@ -539,7 +544,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
if (oldScale != _channel.TextureManager.RenderTargetScale) if (oldScale != _channel.TextureManager.RenderTargetScale)
{ {
_context.Renderer.Pipeline.SetRenderTargetScale(_channel.TextureManager.RenderTargetScale); _context.SupportBufferUpdater.SetRenderTargetScale(_channel.TextureManager.RenderTargetScale);
UpdateViewportTransform(); UpdateViewportTransform();
UpdateScissorState(); UpdateScissorState();
@ -758,9 +763,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
} }
_context.Renderer.Pipeline.SetDepthMode(GetDepthMode()); _context.Renderer.Pipeline.SetDepthMode(GetDepthMode());
_context.Renderer.Pipeline.SetViewports(viewports, disableTransform); _context.Renderer.Pipeline.SetViewports(viewports);
_currentSpecState.SetViewportTransformDisable(_state.State.ViewportTransformEnable == 0); _context.SupportBufferUpdater.SetViewportTransformDisable(
viewports[0].Region.Width,
viewports[0].Region.Height,
_channel.TextureManager.RenderTargetScale,
disableTransform);
_currentSpecState.SetViewportTransformDisable(disableTransform);
_currentSpecState.SetDepthMode(GetDepthMode() == DepthMode.MinusOneToOne); _currentSpecState.SetDepthMode(GetDepthMode() == DepthMode.MinusOneToOne);
} }

View file

@ -85,6 +85,11 @@ namespace Ryujinx.Graphics.Gpu
/// </summary> /// </summary>
internal ConcurrentDictionary<ulong, PhysicalMemory> PhysicalMemoryRegistry { get; } internal ConcurrentDictionary<ulong, PhysicalMemory> PhysicalMemoryRegistry { get; }
/// <summary>
/// Support buffer updater.
/// </summary>
internal SupportBufferUpdater SupportBufferUpdater { get; }
/// <summary> /// <summary>
/// Host hardware capabilities. /// Host hardware capabilities.
/// </summary> /// </summary>
@ -125,6 +130,8 @@ namespace Ryujinx.Graphics.Gpu
PhysicalMemoryRegistry = new ConcurrentDictionary<ulong, PhysicalMemory>(); PhysicalMemoryRegistry = new ConcurrentDictionary<ulong, PhysicalMemory>();
SupportBufferUpdater = new SupportBufferUpdater(renderer);
_firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds); _firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
} }
@ -399,6 +406,8 @@ namespace Ryujinx.Graphics.Gpu
physicalMemory.Dispose(); physicalMemory.Dispose();
} }
SupportBufferUpdater.Dispose();
PhysicalMemoryRegistry.Clear(); PhysicalMemoryRegistry.Clear();
RunDeferredActions(); RunDeferredActions();

View file

@ -278,7 +278,7 @@ namespace Ryujinx.Graphics.Gpu.Image
Debug.Assert(!isView); Debug.Assert(!isView);
TextureCreateInfo createInfo = TextureCache.GetCreateInfo(Info, _context.Capabilities, ScaleFactor); TextureCreateInfo createInfo = TextureCache.GetCreateInfo(Info, _context.Capabilities, ScaleFactor);
HostTexture = _context.Renderer.CreateTexture(createInfo, ScaleFactor); HostTexture = _context.Renderer.CreateTexture(createInfo);
SynchronizeMemory(); // Load the data. SynchronizeMemory(); // Load the data.
if (ScaleMode == TextureScaleMode.Scaled) if (ScaleMode == TextureScaleMode.Scaled)
@ -302,7 +302,7 @@ namespace Ryujinx.Graphics.Gpu.Image
} }
TextureCreateInfo createInfo = TextureCache.GetCreateInfo(Info, _context.Capabilities, ScaleFactor); TextureCreateInfo createInfo = TextureCache.GetCreateInfo(Info, _context.Capabilities, ScaleFactor);
HostTexture = _context.Renderer.CreateTexture(createInfo, ScaleFactor); HostTexture = _context.Renderer.CreateTexture(createInfo);
} }
} }
} }
@ -490,7 +490,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (storage == null) if (storage == null)
{ {
TextureCreateInfo createInfo = TextureCache.GetCreateInfo(Info, _context.Capabilities, scale); TextureCreateInfo createInfo = TextureCache.GetCreateInfo(Info, _context.Capabilities, scale);
storage = _context.Renderer.CreateTexture(createInfo, scale); storage = _context.Renderer.CreateTexture(createInfo);
} }
if (copy) if (copy)

View file

@ -302,7 +302,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_lastFragmentTotal = fragmentTotal; _lastFragmentTotal = fragmentTotal;
_context.Renderer.Pipeline.UpdateRenderScale(_scales, total, fragmentTotal); _context.SupportBufferUpdater.UpdateRenderScale(_scales, total, fragmentTotal);
_scaleChanged = false; _scaleChanged = false;
} }

View file

@ -478,6 +478,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
// Force rebind after doing compute work. // Force rebind after doing compute work.
Rebind(); Rebind();
_context.SupportBufferUpdater.Commit();
} }
/// <summary> /// <summary>
@ -686,6 +688,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
CommitBufferTextureBindings(); CommitBufferTextureBindings();
_rebind = false; _rebind = false;
_context.SupportBufferUpdater.Commit();
} }
/// <summary> /// <summary>

View file

@ -0,0 +1,232 @@
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Memory
{
/// <summary>
/// Support buffer data updater.
/// </summary>
class SupportBufferUpdater : IDisposable
{
private SupportBuffer _data;
private BufferHandle _handle;
private readonly IRenderer _renderer;
private int _startOffset = -1;
private int _endOffset = -1;
/// <summary>
/// Creates a new instance of the support buffer updater.
/// </summary>
/// <param name="renderer">Renderer that the support buffer will be used with</param>
public SupportBufferUpdater(IRenderer renderer)
{
_renderer = renderer;
var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f };
_data.RenderScale.AsSpan().Fill(defaultScale);
DirtyRenderScale(0, SupportBuffer.RenderScaleMaxCount);
}
/// <summary>
/// Mark a region of the support buffer as modified and needing to be sent to the GPU.
/// </summary>
/// <param name="startOffset">Start offset of the region in bytes</param>
/// <param name="byteSize">Size of the region in bytes</param>
private void MarkDirty(int startOffset, int byteSize)
{
int endOffset = startOffset + byteSize;
if (_startOffset == -1)
{
_startOffset = startOffset;
_endOffset = endOffset;
}
else
{
if (startOffset < _startOffset)
{
_startOffset = startOffset;
}
if (endOffset > _endOffset)
{
_endOffset = endOffset;
}
}
}
/// <summary>
/// Marks the fragment render scale count as being modified.
/// </summary>
private void DirtyFragmentRenderScaleCount()
{
MarkDirty(SupportBuffer.FragmentRenderScaleCountOffset, sizeof(int));
}
/// <summary>
/// Marks data of a given type as being modified.
/// </summary>
/// <typeparam name="T">Type of the data</typeparam>
/// <param name="baseOffset">Base offset of the data in bytes</param>
/// <param name="offset">Index of the data, in elements</param>
/// <param name="count">Number of elements</param>
private void DirtyGenericField<T>(int baseOffset, int offset, int count) where T : unmanaged
{
int elemSize = Unsafe.SizeOf<T>();
MarkDirty(baseOffset + offset * elemSize, count * elemSize);
}
/// <summary>
/// Marks render scales as being modified.
/// </summary>
/// <param name="offset">Index of the first scale that was modified</param>
/// <param name="count">Number of modified scales</param>
private void DirtyRenderScale(int offset, int count)
{
DirtyGenericField<Vector4<float>>(SupportBuffer.GraphicsRenderScaleOffset, offset, count);
}
/// <summary>
/// Marks render target BGRA format state as modified.
/// </summary>
/// <param name="offset">Index of the first render target that had its BGRA format modified</param>
/// <param name="count">Number of render targets</param>
private void DirtyFragmentIsBgra(int offset, int count)
{
DirtyGenericField<Vector4<int>>(SupportBuffer.FragmentIsBgraOffset, offset, count);
}
/// <summary>
/// Updates the inverse viewport vector.
/// </summary>
/// <param name="data">Inverse viewport vector</param>
private void UpdateViewportInverse(Vector4<float> data)
{
_data.ViewportInverse = data;
MarkDirty(SupportBuffer.ViewportInverseOffset, SupportBuffer.FieldSize);
}
/// <summary>
/// Sets the scale of all output render targets (they should all have the same scale).
/// </summary>
/// <param name="scale">Scale value</param>
public void SetRenderTargetScale(float scale)
{
_data.RenderScale[0].X = scale;
DirtyRenderScale(0, 1); // Just the first element.
}
/// <summary>
/// Updates the render scales for shader input textures or images.
/// </summary>
/// <param name="scales">Scale values</param>
/// <param name="totalCount">Total number of scales across all stages</param>
/// <param name="fragmentCount">Total number of scales on the fragment shader stage</param>
public void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount)
{
bool changed = false;
for (int index = 0; index < totalCount; index++)
{
if (_data.RenderScale[1 + index].X != scales[index])
{
_data.RenderScale[1 + index].X = scales[index];
changed = true;
}
}
// Only update fragment count if there are scales after it for the vertex stage.
if (fragmentCount != totalCount && fragmentCount != _data.FragmentRenderScaleCount.X)
{
_data.FragmentRenderScaleCount.X = fragmentCount;
DirtyFragmentRenderScaleCount();
}
if (changed)
{
DirtyRenderScale(0, 1 + totalCount);
}
}
/// <summary>
/// Sets whether the format of a given render target is a BGRA format.
/// </summary>
/// <param name="index">Render target index</param>
/// <param name="isBgra">True if the format is BGRA< false otherwise</param>
public void SetRenderTargetIsBgra(int index, bool isBgra)
{
bool isBgraChanged = (_data.FragmentIsBgra[index].X != 0) != isBgra;
if (isBgraChanged)
{
_data.FragmentIsBgra[index].X = isBgra ? 1 : 0;
DirtyFragmentIsBgra(index, 1);
}
}
/// <summary>
/// Sets whether a viewport has transform disabled.
/// </summary>
/// <param name="viewportWidth">Value used as viewport width</param>
/// <param name="viewportHeight">Value used as viewport height</param>
/// <param name="scale">Render target scale</param>
/// <param name="disableTransform">True if transform is disabled, false otherwise</param>
public void SetViewportTransformDisable(float viewportWidth, float viewportHeight, float scale, bool disableTransform)
{
float disableTransformF = disableTransform ? 1.0f : 0.0f;
if (_data.ViewportInverse.W != disableTransformF || disableTransform)
{
UpdateViewportInverse(new Vector4<float>
{
X = scale * 2f / viewportWidth,
Y = scale * 2f / viewportHeight,
Z = 1,
W = disableTransformF
});
}
}
/// <summary>
/// Submits all pending buffer updates to the GPU.
/// </summary>
public void Commit()
{
if (_startOffset != -1)
{
if (_handle == BufferHandle.Null)
{
_handle = _renderer.CreateBuffer(SupportBuffer.RequiredSize);
_renderer.Pipeline.ClearBuffer(_handle, 0, SupportBuffer.RequiredSize, 0);
var range = new BufferRange(_handle, 0, SupportBuffer.RequiredSize);
_renderer.Pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, range) });
}
ReadOnlySpan<byte> data = MemoryMarshal.Cast<SupportBuffer, byte>(MemoryMarshal.CreateSpan(ref _data, 1));
_renderer.SetBufferData(_handle, _startOffset, data.Slice(_startOffset, _endOffset - _startOffset));
_startOffset = -1;
_endOffset = -1;
}
}
/// <summary>
/// Destroys the support buffer.
/// </summary>
public void Dispose()
{
if (_handle != BufferHandle.Null)
{
_renderer.DeleteBuffer(_handle);
_handle = BufferHandle.Null;
}
}
}
}

View file

@ -58,6 +58,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
} }
AddDescriptor(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1); AddDescriptor(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1);
AddUsage(SupportBufferStages, ResourceType.UniformBuffer, ResourceAccess.Read, UniformSetIndex, 0, 1);
_reservedConstantBuffers = 1; // For the support buffer. _reservedConstantBuffers = 1; // For the support buffer.

View file

@ -208,7 +208,16 @@ namespace Ryujinx.Graphics.Gpu
texture.SynchronizeMemory(); texture.SynchronizeMemory();
ImageCrop crop = pt.Crop; ImageCrop crop = new ImageCrop(
(int)(pt.Crop.Left * texture.ScaleFactor),
(int)MathF.Ceiling(pt.Crop.Right * texture.ScaleFactor),
(int)(pt.Crop.Top * texture.ScaleFactor),
(int)MathF.Ceiling(pt.Crop.Bottom * texture.ScaleFactor),
pt.Crop.FlipX,
pt.Crop.FlipY,
pt.Crop.IsStretched,
pt.Crop.AspectRatioX,
pt.Crop.AspectRatioY);
if (texture.Info.Width > pt.Info.Width || texture.Info.Height > pt.Info.Height) if (texture.Info.Width > pt.Info.Width || texture.Info.Height > pt.Info.Height)
{ {

View file

@ -114,7 +114,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects
originalInfo.SwizzleB, originalInfo.SwizzleB,
originalInfo.SwizzleA); originalInfo.SwizzleA);
_intermediaryTexture = new TextureStorage(_renderer, info, view.ScaleFactor); _intermediaryTexture = new TextureStorage(_renderer, info);
_intermediaryTexture.CreateDefaultView(); _intermediaryTexture.CreateDefaultView();
} }

View file

@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects
if (_textureStorage == null || _textureStorage.Info.Width != view.Width || _textureStorage.Info.Height != view.Height) if (_textureStorage == null || _textureStorage.Info.Width != view.Width || _textureStorage.Info.Height != view.Height)
{ {
_textureStorage?.Dispose(); _textureStorage?.Dispose();
_textureStorage = new TextureStorage(_renderer, view.Info, view.ScaleFactor); _textureStorage = new TextureStorage(_renderer, view.Info);
_textureStorage.CreateDefaultView(); _textureStorage.CreateDefaultView();
} }

View file

@ -147,8 +147,8 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
SwizzleComponent.Blue, SwizzleComponent.Blue,
SwizzleComponent.Alpha); SwizzleComponent.Alpha);
_areaTexture = new TextureStorage(_renderer, areaInfo, 1); _areaTexture = new TextureStorage(_renderer, areaInfo);
_searchTexture = new TextureStorage(_renderer, searchInfo, 1); _searchTexture = new TextureStorage(_renderer, searchInfo);
var areaTexture = EmbeddedResources.Read("Ryujinx.Graphics.OpenGL/Effects/Textures/SmaaAreaTexture.bin"); var areaTexture = EmbeddedResources.Read("Ryujinx.Graphics.OpenGL/Effects/Textures/SmaaAreaTexture.bin");
var searchTexture = EmbeddedResources.Read("Ryujinx.Graphics.OpenGL/Effects/Textures/SmaaSearchTexture.bin"); var searchTexture = EmbeddedResources.Read("Ryujinx.Graphics.OpenGL/Effects/Textures/SmaaSearchTexture.bin");
@ -165,11 +165,11 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
if (_outputTexture == null || _outputTexture.Info.Width != view.Width || _outputTexture.Info.Height != view.Height) if (_outputTexture == null || _outputTexture.Info.Width != view.Width || _outputTexture.Info.Height != view.Height)
{ {
_outputTexture?.Dispose(); _outputTexture?.Dispose();
_outputTexture = new TextureStorage(_renderer, view.Info, view.ScaleFactor); _outputTexture = new TextureStorage(_renderer, view.Info);
_outputTexture.CreateDefaultView(); _outputTexture.CreateDefaultView();
_edgeOutputTexture = new TextureStorage(_renderer, view.Info, view.ScaleFactor); _edgeOutputTexture = new TextureStorage(_renderer, view.Info);
_edgeOutputTexture.CreateDefaultView(); _edgeOutputTexture.CreateDefaultView();
_blendOutputTexture = new TextureStorage(_renderer, view.Info, view.ScaleFactor); _blendOutputTexture = new TextureStorage(_renderer, view.Info);
_blendOutputTexture.CreateDefaultView(); _blendOutputTexture.CreateDefaultView();
DeleteShaders(); DeleteShaders();

View file

@ -87,7 +87,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
SwizzleComponent.Red, SwizzleComponent.Red,
SwizzleComponent.Green, SwizzleComponent.Green,
SwizzleComponent.Blue, SwizzleComponent.Blue,
SwizzleComponent.Alpha), 1f); SwizzleComponent.Alpha));
} }
public void Dispose() public void Dispose()

View file

@ -11,15 +11,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
public int Width => Info.Width; public int Width => Info.Width;
public int Height => Info.Height; public int Height => Info.Height;
public float ScaleFactor { get; }
public Target Target => Info.Target; public Target Target => Info.Target;
public Format Format => Info.Format; public Format Format => Info.Format;
public TextureBase(TextureCreateInfo info, float scaleFactor = 1f) public TextureBase(TextureCreateInfo info)
{ {
Info = info; Info = info;
ScaleFactor = scaleFactor;
Handle = GL.GenTexture(); Handle = GL.GenTexture();
} }

View file

@ -349,7 +349,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
public TextureView BgraSwap(TextureView from) public TextureView BgraSwap(TextureView from)
{ {
TextureView to = (TextureView)_renderer.CreateTexture(from.Info, from.ScaleFactor); TextureView to = (TextureView)_renderer.CreateTexture(from.Info);
EnsurePbo(from); EnsurePbo(from);

View file

@ -8,7 +8,6 @@ namespace Ryujinx.Graphics.OpenGL.Image
{ {
public ITextureInfo Storage => this; public ITextureInfo Storage => this;
public int Handle { get; private set; } public int Handle { get; private set; }
public float ScaleFactor { get; private set; }
public TextureCreateInfo Info { get; } public TextureCreateInfo Info { get; }
@ -18,13 +17,12 @@ namespace Ryujinx.Graphics.OpenGL.Image
internal ITexture DefaultView { get; private set; } internal ITexture DefaultView { get; private set; }
public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info, float scaleFactor) public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info)
{ {
_renderer = renderer; _renderer = renderer;
Info = info; Info = info;
Handle = GL.GenTexture(); Handle = GL.GenTexture();
ScaleFactor = scaleFactor;
CreateImmutableStorage(); CreateImmutableStorage();
} }

View file

@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
TextureStorage parent, TextureStorage parent,
TextureCreateInfo info, TextureCreateInfo info,
int firstLayer, int firstLayer,
int firstLevel) : base(info, parent.ScaleFactor) int firstLevel) : base(info)
{ {
_renderer = renderer; _renderer = renderer;
_parent = parent; _parent = parent;

View file

@ -95,7 +95,7 @@ namespace Ryujinx.Graphics.OpenGL
return new Sampler(info); return new Sampler(info);
} }
public ITexture CreateTexture(TextureCreateInfo info, float scaleFactor) public ITexture CreateTexture(TextureCreateInfo info)
{ {
if (info.Target == Target.TextureBuffer) if (info.Target == Target.TextureBuffer)
{ {
@ -103,7 +103,7 @@ namespace Ryujinx.Graphics.OpenGL
} }
else else
{ {
return ResourcePool.GetTextureOrNull(info, scaleFactor) ?? new TextureStorage(this, info, scaleFactor).CreateDefaultView(); return ResourcePool.GetTextureOrNull(info) ?? new TextureStorage(this, info).CreateDefaultView();
} }
} }
@ -194,9 +194,9 @@ namespace Ryujinx.Graphics.OpenGL
ResourcePool.Tick(); ResourcePool.Tick();
} }
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, bool hostReserved) public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved)
{ {
return _counters.QueueReport(type, resultHandler, _pipeline.DrawCount, hostReserved); return _counters.QueueReport(type, resultHandler, divisor, _pipeline.DrawCount, hostReserved);
} }
public void Initialize(GraphicsDebugLevel glLogLevel) public void Initialize(GraphicsDebugLevel glLogLevel)
@ -210,7 +210,6 @@ namespace Ryujinx.Graphics.OpenGL
GL.Arb.MaxShaderCompilerThreads(Math.Min(Environment.ProcessorCount, 8)); GL.Arb.MaxShaderCompilerThreads(Math.Min(Environment.ProcessorCount, 8));
} }
_pipeline.Initialize(this);
_counters.Initialize(_pipeline); _counters.Initialize(_pipeline);
// This is required to disable [0, 1] clamping for SNorm outputs on compatibility profiles. // This is required to disable [0, 1] clamping for SNorm outputs on compatibility profiles.

View file

@ -44,9 +44,7 @@ namespace Ryujinx.Graphics.OpenGL
private CounterQueueEvent _activeConditionalRender; private CounterQueueEvent _activeConditionalRender;
private readonly Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount]; private Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount];
private readonly Vector4<float>[] _renderScale = new Vector4<float>[73];
private int _fragmentScaleCount;
private readonly (TextureBase, Format)[] _images; private readonly (TextureBase, Format)[] _images;
private TextureBase _unit0Texture; private TextureBase _unit0Texture;
@ -66,7 +64,6 @@ namespace Ryujinx.Graphics.OpenGL
private bool _tfEnabled; private bool _tfEnabled;
private TransformFeedbackPrimitiveType _tfTopology; private TransformFeedbackPrimitiveType _tfTopology;
private SupportBufferUpdater _supportBuffer;
private readonly BufferHandle[] _tfbs; private readonly BufferHandle[] _tfbs;
private readonly BufferRange[] _tfbTargets; private readonly BufferRange[] _tfbTargets;
@ -84,22 +81,10 @@ namespace Ryujinx.Graphics.OpenGL
_images = new (TextureBase, Format)[SavedImages]; _images = new (TextureBase, Format)[SavedImages];
var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f };
new Span<Vector4<float>>(_renderScale).Fill(defaultScale);
_tfbs = new BufferHandle[Constants.MaxTransformFeedbackBuffers]; _tfbs = new BufferHandle[Constants.MaxTransformFeedbackBuffers];
_tfbTargets = new BufferRange[Constants.MaxTransformFeedbackBuffers]; _tfbTargets = new BufferRange[Constants.MaxTransformFeedbackBuffers];
} }
public void Initialize(OpenGLRenderer renderer)
{
_supportBuffer = new SupportBufferUpdater(renderer);
GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, Unsafe.As<BufferHandle, int>(ref _supportBuffer.Handle));
_supportBuffer.UpdateFragmentIsBgra(_fpIsBgra, 0, SupportBuffer.FragmentIsBgraCount);
_supportBuffer.UpdateRenderScale(_renderScale, 0, SupportBuffer.RenderScaleMaxCount);
}
public void Barrier() public void Barrier()
{ {
GL.MemoryBarrier(MemoryBarrierFlags.AllBarrierBits); GL.MemoryBarrier(MemoryBarrierFlags.AllBarrierBits);
@ -684,8 +669,6 @@ namespace Ryujinx.Graphics.OpenGL
{ {
if (texture is TextureView view && sampler is Sampler samp) if (texture is TextureView view && sampler is Sampler samp)
{ {
_supportBuffer.Commit();
if (HwCapabilities.SupportsDrawTexture) if (HwCapabilities.SupportsDrawTexture)
{ {
GL.NV.DrawTexture( GL.NV.DrawTexture(
@ -777,16 +760,6 @@ namespace Ryujinx.Graphics.OpenGL
_tfEnabled = false; _tfEnabled = false;
} }
public double GetCounterDivisor(CounterType type)
{
if (type == CounterType.SamplesPassed)
{
return _renderScale[0].X * _renderScale[0].X;
}
return 1;
}
public void SetAlphaTest(bool enable, float reference, CompareOp op) public void SetAlphaTest(bool enable, float reference, CompareOp op)
{ {
if (!enable) if (!enable)
@ -1172,12 +1145,6 @@ namespace Ryujinx.Graphics.OpenGL
_rasterizerDiscard = discard; _rasterizerDiscard = discard;
} }
public void SetRenderTargetScale(float scale)
{
_renderScale[0].X = scale;
_supportBuffer.UpdateRenderScale(_renderScale, 0, 1); // Just the first element.
}
public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks) public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks)
{ {
_componentMasks = 0; _componentMasks = 0;
@ -1194,8 +1161,6 @@ namespace Ryujinx.Graphics.OpenGL
{ {
EnsureFramebuffer(); EnsureFramebuffer();
bool isBgraChanged = false;
for (int index = 0; index < colors.Length; index++) for (int index = 0; index < colors.Length; index++)
{ {
TextureView color = (TextureView)colors[index]; TextureView color = (TextureView)colors[index];
@ -1209,18 +1174,12 @@ namespace Ryujinx.Graphics.OpenGL
if (_fpIsBgra[index].X != isBgra) if (_fpIsBgra[index].X != isBgra)
{ {
_fpIsBgra[index].X = isBgra; _fpIsBgra[index].X = isBgra;
isBgraChanged = true;
RestoreComponentMask(index); RestoreComponentMask(index);
} }
} }
} }
if (isBgraChanged)
{
_supportBuffer.UpdateFragmentIsBgra(_fpIsBgra, 0, SupportBuffer.FragmentIsBgraCount);
}
TextureView depthStencilView = (TextureView)depthStencil; TextureView depthStencilView = (TextureView)depthStencil;
_framebuffer.AttachDepthStencil(depthStencilView); _framebuffer.AttachDepthStencil(depthStencilView);
@ -1411,7 +1370,7 @@ namespace Ryujinx.Graphics.OpenGL
_vertexArray.SetVertexBuffers(vertexBuffers); _vertexArray.SetVertexBuffers(vertexBuffers);
} }
public void SetViewports(ReadOnlySpan<Viewport> viewports, bool disableTransform) public void SetViewports(ReadOnlySpan<Viewport> viewports)
{ {
Array.Resize(ref _viewportArray, viewports.Length * 4); Array.Resize(ref _viewportArray, viewports.Length * 4);
Array.Resize(ref _depthRangeArray, viewports.Length * 2); Array.Resize(ref _depthRangeArray, viewports.Length * 2);
@ -1450,19 +1409,6 @@ namespace Ryujinx.Graphics.OpenGL
GL.ViewportArray(0, viewports.Length, viewportArray); GL.ViewportArray(0, viewports.Length, viewportArray);
GL.DepthRangeArray(0, viewports.Length, depthRangeArray); GL.DepthRangeArray(0, viewports.Length, depthRangeArray);
float disableTransformF = disableTransform ? 1.0f : 0.0f;
if (_supportBuffer.Data.ViewportInverse.W != disableTransformF || disableTransform)
{
float scale = _renderScale[0].X;
_supportBuffer.UpdateViewportInverse(new Vector4<float>
{
X = scale * 2f / viewports[0].Region.Width,
Y = scale * 2f / viewports[0].Region.Height,
Z = 1,
W = disableTransformF
});
}
} }
public void TextureBarrier() public void TextureBarrier()
@ -1552,36 +1498,9 @@ namespace Ryujinx.Graphics.OpenGL
return (_boundDrawFramebuffer, _boundReadFramebuffer); return (_boundDrawFramebuffer, _boundReadFramebuffer);
} }
public void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount)
{
bool changed = false;
for (int index = 0; index < totalCount; index++)
{
if (_renderScale[1 + index].X != scales[index])
{
_renderScale[1 + index].X = scales[index];
changed = true;
}
}
// Only update fragment count if there are scales after it for the vertex stage.
if (fragmentCount != totalCount && fragmentCount != _fragmentScaleCount)
{
_fragmentScaleCount = fragmentCount;
_supportBuffer.UpdateFragmentRenderScaleCount(_fragmentScaleCount);
}
if (changed)
{
_supportBuffer.UpdateRenderScale(_renderScale, 0, 1 + totalCount);
}
}
private void PrepareForDispatch() private void PrepareForDispatch()
{ {
_unit0Texture?.Bind(0); _unit0Texture?.Bind(0);
_supportBuffer.Commit();
} }
private void PreDraw(int vertexCount) private void PreDraw(int vertexCount)
@ -1601,7 +1520,6 @@ namespace Ryujinx.Graphics.OpenGL
DrawCount++; DrawCount++;
_unit0Texture?.Bind(0); _unit0Texture?.Bind(0);
_supportBuffer.Commit();
} }
private void PostDraw() private void PostDraw()
@ -1752,8 +1670,6 @@ namespace Ryujinx.Graphics.OpenGL
public void Dispose() public void Dispose()
{ {
_supportBuffer?.Dispose();
for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++) for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++)
{ {
if (_tfbs[i] != BufferHandle.Null) if (_tfbs[i] != BufferHandle.Null)

View file

@ -107,7 +107,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
} }
} }
public CounterQueueEvent QueueReport(EventHandler<ulong> resultHandler, ulong lastDrawIndex, bool hostReserved) public CounterQueueEvent QueueReport(EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, bool hostReserved)
{ {
CounterQueueEvent result; CounterQueueEvent result;
ulong draws = lastDrawIndex - _current.DrawIndex; ulong draws = lastDrawIndex - _current.DrawIndex;
@ -123,7 +123,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
_current.ReserveForHostAccess(); _current.ReserveForHostAccess();
} }
_current.Complete(draws > 0, _pipeline.GetCounterDivisor(Type)); _current.Complete(draws > 0, divisor);
_events.Enqueue(_current); _events.Enqueue(_current);
_current.OnResult += resultHandler; _current.OnResult += resultHandler;

View file

@ -23,9 +23,9 @@ namespace Ryujinx.Graphics.OpenGL.Queries
} }
} }
public CounterQueueEvent QueueReport(CounterType type, EventHandler<ulong> resultHandler, ulong lastDrawIndex, bool hostReserved) public CounterQueueEvent QueueReport(CounterType type, EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, bool hostReserved)
{ {
return _counterQueues[(int)type].QueueReport(resultHandler, lastDrawIndex, hostReserved); return _counterQueues[(int)type].QueueReport(resultHandler, divisor, lastDrawIndex, hostReserved);
} }
public void QueueReset(CounterType type) public void QueueReset(CounterType type)

View file

@ -9,7 +9,6 @@ namespace Ryujinx.Graphics.OpenGL
{ {
public TextureCreateInfo Info; public TextureCreateInfo Info;
public TextureView View; public TextureView View;
public float ScaleFactor;
public int RemainingFrames; public int RemainingFrames;
} }
@ -42,7 +41,6 @@ namespace Ryujinx.Graphics.OpenGL
{ {
Info = view.Info, Info = view.Info,
View = view, View = view,
ScaleFactor = view.ScaleFactor,
RemainingFrames = DisposedLiveFrames RemainingFrames = DisposedLiveFrames
}); });
} }
@ -52,9 +50,8 @@ namespace Ryujinx.Graphics.OpenGL
/// Attempt to obtain a texture from the resource cache with the desired parameters. /// Attempt to obtain a texture from the resource cache with the desired parameters.
/// </summary> /// </summary>
/// <param name="info">The creation info for the desired texture</param> /// <param name="info">The creation info for the desired texture</param>
/// <param name="scaleFactor">The scale factor for the desired texture</param>
/// <returns>A TextureView with the description specified, or null if one was not found.</returns> /// <returns>A TextureView with the description specified, or null if one was not found.</returns>
public TextureView GetTextureOrNull(TextureCreateInfo info, float scaleFactor) public TextureView GetTextureOrNull(TextureCreateInfo info)
{ {
lock (_lock) lock (_lock)
{ {
@ -64,13 +61,10 @@ namespace Ryujinx.Graphics.OpenGL
} }
foreach (DisposedTexture texture in list) foreach (DisposedTexture texture in list)
{
if (scaleFactor == texture.ScaleFactor)
{ {
list.Remove(texture); list.Remove(texture);
return texture.View; return texture.View;
} }
}
return null; return null;
} }

View file

@ -111,12 +111,11 @@ namespace Ryujinx.Graphics.OpenGL
GL.Clear(ClearBufferMask.ColorBufferBit); GL.Clear(ClearBufferMask.ColorBufferBit);
int srcX0, srcX1, srcY0, srcY1; int srcX0, srcX1, srcY0, srcY1;
float scale = viewConverted.ScaleFactor;
if (crop.Left == 0 && crop.Right == 0) if (crop.Left == 0 && crop.Right == 0)
{ {
srcX0 = 0; srcX0 = 0;
srcX1 = (int)(viewConverted.Width / scale); srcX1 = viewConverted.Width;
} }
else else
{ {
@ -127,7 +126,7 @@ namespace Ryujinx.Graphics.OpenGL
if (crop.Top == 0 && crop.Bottom == 0) if (crop.Top == 0 && crop.Bottom == 0)
{ {
srcY0 = 0; srcY0 = 0;
srcY1 = (int)(viewConverted.Height / scale); srcY1 = viewConverted.Height;
} }
else else
{ {
@ -135,14 +134,6 @@ namespace Ryujinx.Graphics.OpenGL
srcY1 = crop.Bottom; srcY1 = crop.Bottom;
} }
if (scale != 1f)
{
srcX0 = (int)(srcX0 * scale);
srcY0 = (int)(srcY0 * scale);
srcX1 = (int)Math.Ceiling(srcX1 * scale);
srcY1 = (int)Math.Ceiling(srcY1 * scale);
}
float ratioX = crop.IsStretched ? 1.0f : MathF.Min(1.0f, _height * crop.AspectRatioX / (_width * crop.AspectRatioY)); float ratioX = crop.IsStretched ? 1.0f : MathF.Min(1.0f, _height * crop.AspectRatioX / (_width * crop.AspectRatioY));
float ratioY = crop.IsStretched ? 1.0f : MathF.Min(1.0f, _width * crop.AspectRatioY / (_height * crop.AspectRatioX)); float ratioY = crop.IsStretched ? 1.0f : MathF.Min(1.0f, _width * crop.AspectRatioY / (_height * crop.AspectRatioX));
@ -408,7 +399,7 @@ namespace Ryujinx.Graphics.OpenGL
SwizzleComponent.Alpha); SwizzleComponent.Alpha);
_isBgra = forceBgra; _isBgra = forceBgra;
_upscaledTexture = _renderer.CreateTexture(info, 1) as TextureView; _upscaledTexture = _renderer.CreateTexture(info) as TextureView;
} }
public void SetScalingFilterLevel(float level) public void SetScalingFilterLevel(float level)

View file

@ -35,7 +35,6 @@ namespace Ryujinx.Graphics.Vulkan
private readonly bool[] _uniformSet; private readonly bool[] _uniformSet;
private readonly bool[] _storageSet; private readonly bool[] _storageSet;
private Buffer _cachedSupportBuffer;
[Flags] [Flags]
private enum DirtyFlags private enum DirtyFlags
@ -115,7 +114,7 @@ namespace Ryujinx.Graphics.Vulkan
SwizzleComponent.Red, SwizzleComponent.Red,
SwizzleComponent.Green, SwizzleComponent.Green,
SwizzleComponent.Blue, SwizzleComponent.Blue,
SwizzleComponent.Alpha), 1f); SwizzleComponent.Alpha));
_dummySampler = (SamplerHolder)gd.CreateSampler(new SamplerCreateInfo( _dummySampler = (SamplerHolder)gd.CreateSampler(new SamplerCreateInfo(
MinFilter.Nearest, MinFilter.Nearest,
@ -392,26 +391,6 @@ namespace Ryujinx.Graphics.Vulkan
{ {
Initialize(cbs, setIndex, dsc); Initialize(cbs, setIndex, dsc);
} }
if (setIndex == PipelineBase.UniformSetIndex)
{
Span<DescriptorBufferInfo> uniformBuffer = stackalloc DescriptorBufferInfo[1];
if (!_uniformSet[0])
{
_cachedSupportBuffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value;
_uniformSet[0] = true;
}
uniformBuffer[0] = new DescriptorBufferInfo
{
Offset = 0,
Range = (ulong)SupportBuffer.RequiredSize,
Buffer = _cachedSupportBuffer,
};
dsc.UpdateBuffers(0, 0, uniformBuffer, DescriptorType.UniformBuffer);
}
} }
foreach (ResourceBindingSegment segment in bindingSegments) foreach (ResourceBindingSegment segment in bindingSegments)
@ -553,22 +532,6 @@ namespace Ryujinx.Graphics.Vulkan
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void UpdateAndBindUniformBufferPd(CommandBufferScoped cbs, PipelineBindPoint pbp) private void UpdateAndBindUniformBufferPd(CommandBufferScoped cbs, PipelineBindPoint pbp)
{ {
if (!_uniformSet[0])
{
Span<DescriptorBufferInfo> uniformBuffer = stackalloc DescriptorBufferInfo[1];
uniformBuffer[0] = new DescriptorBufferInfo
{
Offset = 0,
Range = (ulong)SupportBuffer.RequiredSize,
Buffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value,
};
_uniformSet[0] = true;
UpdateBuffers(cbs, pbp, 0, uniformBuffer, DescriptorType.UniformBuffer);
}
var bindingSegments = _program.BindingSegments[PipelineBase.UniformSetIndex]; var bindingSegments = _program.BindingSegments[PipelineBase.UniformSetIndex];
var dummyBuffer = _dummyBuffer?.GetBuffer(); var dummyBuffer = _dummyBuffer?.GetBuffer();

View file

@ -115,7 +115,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
originalInfo.SwizzleB, originalInfo.SwizzleB,
originalInfo.SwizzleA); originalInfo.SwizzleA);
_intermediaryTexture?.Dispose(); _intermediaryTexture?.Dispose();
_intermediaryTexture = _renderer.CreateTexture(info, view.ScaleFactor) as TextureView; _intermediaryTexture = _renderer.CreateTexture(info) as TextureView;
} }
_pipeline.SetCommandBuffer(cbs); _pipeline.SetCommandBuffer(cbs);

View file

@ -57,7 +57,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
if (_texture == null || _texture.Width != view.Width || _texture.Height != view.Height) if (_texture == null || _texture.Width != view.Width || _texture.Height != view.Height)
{ {
_texture?.Dispose(); _texture?.Dispose();
_texture = _renderer.CreateTexture(view.Info, view.ScaleFactor) as TextureView; _texture = _renderer.CreateTexture(view.Info) as TextureView;
} }
_pipeline.SetCommandBuffer(cbs); _pipeline.SetCommandBuffer(cbs);

View file

@ -177,8 +177,8 @@ namespace Ryujinx.Graphics.Vulkan.Effects
var areaTexture = EmbeddedResources.Read("Ryujinx.Graphics.Vulkan/Effects/Textures/SmaaAreaTexture.bin"); var areaTexture = EmbeddedResources.Read("Ryujinx.Graphics.Vulkan/Effects/Textures/SmaaAreaTexture.bin");
var searchTexture = EmbeddedResources.Read("Ryujinx.Graphics.Vulkan/Effects/Textures/SmaaSearchTexture.bin"); var searchTexture = EmbeddedResources.Read("Ryujinx.Graphics.Vulkan/Effects/Textures/SmaaSearchTexture.bin");
_areaTexture = _renderer.CreateTexture(areaInfo, 1) as TextureView; _areaTexture = _renderer.CreateTexture(areaInfo) as TextureView;
_searchTexture = _renderer.CreateTexture(searchInfo, 1) as TextureView; _searchTexture = _renderer.CreateTexture(searchInfo) as TextureView;
_areaTexture.SetData(areaTexture); _areaTexture.SetData(areaTexture);
_searchTexture.SetData(searchTexture); _searchTexture.SetData(searchTexture);
@ -193,9 +193,9 @@ namespace Ryujinx.Graphics.Vulkan.Effects
_edgeOutputTexture?.Dispose(); _edgeOutputTexture?.Dispose();
_blendOutputTexture?.Dispose(); _blendOutputTexture?.Dispose();
_outputTexture = _renderer.CreateTexture(view.Info, view.ScaleFactor) as TextureView; _outputTexture = _renderer.CreateTexture(view.Info) as TextureView;
_edgeOutputTexture = _renderer.CreateTexture(view.Info, view.ScaleFactor) as TextureView; _edgeOutputTexture = _renderer.CreateTexture(view.Info) as TextureView;
_blendOutputTexture = _renderer.CreateTexture(view.Info, view.ScaleFactor) as TextureView; _blendOutputTexture = _renderer.CreateTexture(view.Info) as TextureView;
} }
_pipeline.SetCommandBuffer(cbs); _pipeline.SetCommandBuffer(cbs);

View file

@ -168,6 +168,16 @@ namespace Ryujinx.Graphics.Vulkan
return ComponentType.Float; return ComponentType.Float;
} }
public ImageAspectFlags GetDepthStencilAspectFlags()
{
if (_depthStencil == null)
{
return ImageAspectFlags.None;
}
return _depthStencil.Info.Format.ConvertAspectFlags();
}
public bool IsValidColorAttachment(int bindIndex) public bool IsValidColorAttachment(int bindIndex)
{ {
return (uint)bindIndex < Constants.MaxRenderTargets && (_validColorAttachments & (1u << bindIndex)) != 0; return (uint)bindIndex < Constants.MaxRenderTargets && (_validColorAttachments & (1u << bindIndex)) != 0;
@ -226,7 +236,7 @@ namespace Ryujinx.Graphics.Vulkan
_depthStencil?.Storage.SetModification( _depthStencil?.Storage.SetModification(
AccessFlags.DepthStencilAttachmentWriteBit, AccessFlags.DepthStencilAttachmentWriteBit,
PipelineStageFlags.ColorAttachmentOutputBit); PipelineStageFlags.LateFragmentTestsBit);
} }
public void InsertClearBarrier(CommandBufferScoped cbs, int index) public void InsertClearBarrier(CommandBufferScoped cbs, int index)

View file

@ -1,10 +1,11 @@
using Ryujinx.Graphics.GAL; using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using Ryujinx.Graphics.Vulkan.Shaders;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Numerics; using System.Numerics;
using CompareOp = Ryujinx.Graphics.GAL.CompareOp; using CompareOp = Ryujinx.Graphics.GAL.CompareOp;
using Format = Ryujinx.Graphics.GAL.Format; using Format = Ryujinx.Graphics.GAL.Format;
@ -26,6 +27,7 @@ namespace Ryujinx.Graphics.Vulkan
class HelperShader : IDisposable class HelperShader : IDisposable
{ {
private const int UniformBufferAlignment = 256; private const int UniformBufferAlignment = 256;
private const string ShaderBinariesPath = "Ryujinx.Graphics.Vulkan/Shaders/SpirvBinaries";
private readonly PipelineHelperShader _pipeline; private readonly PipelineHelperShader _pipeline;
private readonly ISampler _samplerLinear; private readonly ISampler _samplerLinear;
@ -67,40 +69,40 @@ namespace Ryujinx.Graphics.Vulkan
_programColorBlit = gd.CreateProgramWithMinimalLayout(new[] _programColorBlit = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorBlitVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.ColorBlitFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorBlitFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, blitResourceLayout); }, blitResourceLayout);
_programColorBlitMs = gd.CreateProgramWithMinimalLayout(new[] _programColorBlitMs = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorBlitVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.ColorBlitMsFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorBlitMsFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, blitResourceLayout); }, blitResourceLayout);
_programColorBlitClearAlpha = gd.CreateProgramWithMinimalLayout(new[] _programColorBlitClearAlpha = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorBlitVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.ColorBlitClearAlphaFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorBlitClearAlphaFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, blitResourceLayout); }, blitResourceLayout);
var colorClearResourceLayout = new ResourceLayoutBuilder().Add(ResourceStages.Vertex, ResourceType.UniformBuffer, 1).Build(); var colorClearResourceLayout = new ResourceLayoutBuilder().Add(ResourceStages.Vertex, ResourceType.UniformBuffer, 1).Build();
_programColorClearF = gd.CreateProgramWithMinimalLayout(new[] _programColorClearF = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorClearVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.ColorClearFFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorClearFFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, colorClearResourceLayout); }, colorClearResourceLayout);
_programColorClearSI = gd.CreateProgramWithMinimalLayout(new[] _programColorClearSI = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorClearVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.ColorClearSIFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorClearSIFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, colorClearResourceLayout); }, colorClearResourceLayout);
_programColorClearUI = gd.CreateProgramWithMinimalLayout(new[] _programColorClearUI = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorClearVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.ColorClearUIFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorClearUIFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, colorClearResourceLayout); }, colorClearResourceLayout);
var strideChangeResourceLayout = new ResourceLayoutBuilder() var strideChangeResourceLayout = new ResourceLayoutBuilder()
@ -110,7 +112,7 @@ namespace Ryujinx.Graphics.Vulkan
_programStrideChange = gd.CreateProgramWithMinimalLayout(new[] _programStrideChange = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ChangeBufferStrideShaderSource, ShaderStage.Compute, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ChangeBufferStride.spv"), ShaderStage.Compute, TargetLanguage.Spirv),
}, strideChangeResourceLayout); }, strideChangeResourceLayout);
var colorCopyResourceLayout = new ResourceLayoutBuilder() var colorCopyResourceLayout = new ResourceLayoutBuilder()
@ -120,17 +122,17 @@ namespace Ryujinx.Graphics.Vulkan
_programColorCopyShortening = gd.CreateProgramWithMinimalLayout(new[] _programColorCopyShortening = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorCopyShorteningComputeShaderSource, ShaderStage.Compute, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorCopyShorteningCompute.spv"), ShaderStage.Compute, TargetLanguage.Spirv),
}, colorCopyResourceLayout); }, colorCopyResourceLayout);
_programColorCopyToNonMs = gd.CreateProgramWithMinimalLayout(new[] _programColorCopyToNonMs = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorCopyToNonMsComputeShaderSource, ShaderStage.Compute, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorCopyToNonMsCompute.spv"), ShaderStage.Compute, TargetLanguage.Spirv),
}, colorCopyResourceLayout); }, colorCopyResourceLayout);
_programColorCopyWidening = gd.CreateProgramWithMinimalLayout(new[] _programColorCopyWidening = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorCopyWideningComputeShaderSource, ShaderStage.Compute, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorCopyWideningCompute.spv"), ShaderStage.Compute, TargetLanguage.Spirv),
}, colorCopyResourceLayout); }, colorCopyResourceLayout);
var colorDrawToMsResourceLayout = new ResourceLayoutBuilder() var colorDrawToMsResourceLayout = new ResourceLayoutBuilder()
@ -139,8 +141,8 @@ namespace Ryujinx.Graphics.Vulkan
_programColorDrawToMs = gd.CreateProgramWithMinimalLayout(new[] _programColorDrawToMs = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorDrawToMsVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorDrawToMsVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.ColorDrawToMsFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorDrawToMsFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, colorDrawToMsResourceLayout); }, colorDrawToMsResourceLayout);
var convertD32S8ToD24S8ResourceLayout = new ResourceLayoutBuilder() var convertD32S8ToD24S8ResourceLayout = new ResourceLayoutBuilder()
@ -150,7 +152,7 @@ namespace Ryujinx.Graphics.Vulkan
_programConvertD32S8ToD24S8 = gd.CreateProgramWithMinimalLayout(new[] _programConvertD32S8ToD24S8 = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ConvertD32S8ToD24S8ShaderSource, ShaderStage.Compute, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ConvertD32S8ToD24S8.spv"), ShaderStage.Compute, TargetLanguage.Spirv),
}, convertD32S8ToD24S8ResourceLayout); }, convertD32S8ToD24S8ResourceLayout);
var convertIndexBufferResourceLayout = new ResourceLayoutBuilder() var convertIndexBufferResourceLayout = new ResourceLayoutBuilder()
@ -160,7 +162,7 @@ namespace Ryujinx.Graphics.Vulkan
_programConvertIndexBuffer = gd.CreateProgramWithMinimalLayout(new[] _programConvertIndexBuffer = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ConvertIndexBufferShaderSource, ShaderStage.Compute, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ConvertIndexBuffer.spv"), ShaderStage.Compute, TargetLanguage.Spirv),
}, convertIndexBufferResourceLayout); }, convertIndexBufferResourceLayout);
var convertIndirectDataResourceLayout = new ResourceLayoutBuilder() var convertIndirectDataResourceLayout = new ResourceLayoutBuilder()
@ -171,61 +173,66 @@ namespace Ryujinx.Graphics.Vulkan
_programConvertIndirectData = gd.CreateProgramWithMinimalLayout(new[] _programConvertIndirectData = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ConvertIndirectDataShaderSource, ShaderStage.Compute, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ConvertIndirectData.spv"), ShaderStage.Compute, TargetLanguage.Spirv),
}, convertIndirectDataResourceLayout); }, convertIndirectDataResourceLayout);
_programDepthBlit = gd.CreateProgramWithMinimalLayout(new[] _programDepthBlit = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorBlitVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.DepthBlitFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("DepthBlitFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, blitResourceLayout); }, blitResourceLayout);
_programDepthBlitMs = gd.CreateProgramWithMinimalLayout(new[] _programDepthBlitMs = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorBlitVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.DepthBlitMsFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("DepthBlitMsFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, blitResourceLayout); }, blitResourceLayout);
_programDepthDrawToMs = gd.CreateProgramWithMinimalLayout(new[] _programDepthDrawToMs = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorDrawToMsVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorDrawToMsVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.DepthDrawToMsFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("DepthDrawToMsFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, colorDrawToMsResourceLayout); }, colorDrawToMsResourceLayout);
_programDepthDrawToNonMs = gd.CreateProgramWithMinimalLayout(new[] _programDepthDrawToNonMs = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorDrawToMsVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorDrawToMsVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.DepthDrawToNonMsFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("DepthDrawToNonMsFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, colorDrawToMsResourceLayout); }, colorDrawToMsResourceLayout);
if (gd.Capabilities.SupportsShaderStencilExport) if (gd.Capabilities.SupportsShaderStencilExport)
{ {
_programStencilBlit = gd.CreateProgramWithMinimalLayout(new[] _programStencilBlit = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorBlitVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.StencilBlitFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("StencilBlitFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, blitResourceLayout); }, blitResourceLayout);
_programStencilBlitMs = gd.CreateProgramWithMinimalLayout(new[] _programStencilBlitMs = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorBlitVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.StencilBlitMsFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("StencilBlitMsFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, blitResourceLayout); }, blitResourceLayout);
_programStencilDrawToMs = gd.CreateProgramWithMinimalLayout(new[] _programStencilDrawToMs = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorDrawToMsVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorDrawToMsVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.StencilDrawToMsFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("StencilDrawToMsFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, colorDrawToMsResourceLayout); }, colorDrawToMsResourceLayout);
_programStencilDrawToNonMs = gd.CreateProgramWithMinimalLayout(new[] _programStencilDrawToNonMs = gd.CreateProgramWithMinimalLayout(new[]
{ {
new ShaderSource(ShaderBinaries.ColorDrawToMsVertexShaderSource, ShaderStage.Vertex, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("ColorDrawToMsVertex.spv"), ShaderStage.Vertex, TargetLanguage.Spirv),
new ShaderSource(ShaderBinaries.StencilDrawToNonMsFragmentShaderSource, ShaderStage.Fragment, TargetLanguage.Spirv), new ShaderSource(ReadSpirv("StencilDrawToNonMsFragment.spv"), ShaderStage.Fragment, TargetLanguage.Spirv),
}, colorDrawToMsResourceLayout); }, colorDrawToMsResourceLayout);
} }
} }
private static byte[] ReadSpirv(string fileName)
{
return EmbeddedResources.Read(string.Join('/', ShaderBinariesPath, fileName));
}
public void Blit( public void Blit(
VulkanRenderer gd, VulkanRenderer gd,
TextureView src, TextureView src,
@ -470,7 +477,7 @@ namespace Ryujinx.Graphics.Vulkan
_pipeline.ClearRenderTargetColor(0, 0, 1, new ColorF(0f, 0f, 0f, 1f)); _pipeline.ClearRenderTargetColor(0, 0, 1, new ColorF(0f, 0f, 0f, 1f));
} }
_pipeline.SetViewports(viewports, false); _pipeline.SetViewports(viewports);
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
_pipeline.Draw(4, 1, 0, 0); _pipeline.Draw(4, 1, 0, 0);
@ -546,7 +553,7 @@ namespace Ryujinx.Graphics.Vulkan
_pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, (uint)dstSamples, true, dstFormat); _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, (uint)dstSamples, true, dstFormat);
_pipeline.SetScissors(scissors); _pipeline.SetScissors(scissors);
_pipeline.SetViewports(viewports, false); _pipeline.SetViewports(viewports);
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
var aspectFlags = src.Info.Format.ConvertAspectFlags(); var aspectFlags = src.Info.Format.ConvertAspectFlags();
@ -710,7 +717,7 @@ namespace Ryujinx.Graphics.Vulkan
_pipeline.SetProgram(program); _pipeline.SetProgram(program);
_pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false, dstFormat); _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false, dstFormat);
_pipeline.SetRenderTargetColorMasks(new[] { componentMask }); _pipeline.SetRenderTargetColorMasks(new[] { componentMask });
_pipeline.SetViewports(viewports, false); _pipeline.SetViewports(viewports);
_pipeline.SetScissors(scissors); _pipeline.SetScissors(scissors);
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
_pipeline.Draw(4, 1, 0, 0); _pipeline.Draw(4, 1, 0, 0);
@ -774,7 +781,7 @@ namespace Ryujinx.Graphics.Vulkan
Span<Rectangle<int>> scissors = stackalloc Rectangle<int>[1]; Span<Rectangle<int>> scissors = stackalloc Rectangle<int>[1];
pipeline.SetProgram(_programColorBlit); pipeline.SetProgram(_programColorBlit);
pipeline.SetViewports(viewports, false); pipeline.SetViewports(viewports);
pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
pipeline.Draw(4, 1, 0, 0); pipeline.Draw(4, 1, 0, 0);
@ -1117,7 +1124,7 @@ namespace Ryujinx.Graphics.Vulkan
scissors[0] = new Rectangle<int>(0, 0, dst.Width, dst.Height); scissors[0] = new Rectangle<int>(0, 0, dst.Width, dst.Height);
_pipeline.SetScissors(scissors); _pipeline.SetScissors(scissors);
_pipeline.SetViewports(viewports, false); _pipeline.SetViewports(viewports);
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
for (int z = 0; z < depth; z++) for (int z = 0; z < depth; z++)
@ -1250,7 +1257,7 @@ namespace Ryujinx.Graphics.Vulkan
_pipeline.SetRenderTargetColorMasks(new uint[] { 0xf }); _pipeline.SetRenderTargetColorMasks(new uint[] { 0xf });
_pipeline.SetScissors(scissors); _pipeline.SetScissors(scissors);
_pipeline.SetViewports(viewports, false); _pipeline.SetViewports(viewports);
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
_pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) });

View file

@ -152,9 +152,6 @@ namespace Ryujinx.Graphics.Vulkan
{ {
if (_buffer == from) if (_buffer == from)
{ {
_buffer.DecrementReferenceCount();
to.IncrementReferenceCount();
_buffer = to; _buffer = to;
} }
} }

View file

@ -50,9 +50,6 @@ namespace Ryujinx.Graphics.Vulkan
private ShaderCollection _program; private ShaderCollection _program;
private readonly Vector4<float>[] _renderScale = new Vector4<float>[73];
private int _fragmentScaleCount;
protected FramebufferParams FramebufferParams; protected FramebufferParams FramebufferParams;
private Auto<DisposableFramebuffer> _framebuffer; private Auto<DisposableFramebuffer> _framebuffer;
private Auto<DisposableRenderPass> _renderPass; private Auto<DisposableRenderPass> _renderPass;
@ -74,7 +71,6 @@ namespace Ryujinx.Graphics.Vulkan
private readonly VertexBufferUpdater _vertexBufferUpdater; private readonly VertexBufferUpdater _vertexBufferUpdater;
public SupportBufferUpdater SupportBufferUpdater;
public IndexBufferPattern QuadsToTrisPattern; public IndexBufferPattern QuadsToTrisPattern;
public IndexBufferPattern TriFanToTrisPattern; public IndexBufferPattern TriFanToTrisPattern;
@ -119,9 +115,6 @@ namespace Ryujinx.Graphics.Vulkan
ClearScissor = new Rectangle<int>(0, 0, 0xffff, 0xffff); ClearScissor = new Rectangle<int>(0, 0, 0xffff, 0xffff);
var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f };
new Span<Vector4<float>>(_renderScale).Fill(defaultScale);
_storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets]; _storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets];
_newState.Initialize(); _newState.Initialize();
@ -131,9 +124,6 @@ namespace Ryujinx.Graphics.Vulkan
{ {
_descriptorSetUpdater.Initialize(); _descriptorSetUpdater.Initialize();
SupportBufferUpdater = new SupportBufferUpdater(Gd);
SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, SupportBuffer.RenderScaleMaxCount);
QuadsToTrisPattern = new IndexBufferPattern(Gd, 4, 6, 0, new[] { 0, 1, 2, 0, 2, 3 }, 4, false); QuadsToTrisPattern = new IndexBufferPattern(Gd, 4, 6, 0, new[] { 0, 1, 2, 0, 2, 3 }, 4, false);
TriFanToTrisPattern = new IndexBufferPattern(Gd, 3, 3, 2, new[] { int.MinValue, -1, 0 }, 1, true); TriFanToTrisPattern = new IndexBufferPattern(Gd, 3, 3, 2, new[] { int.MinValue, -1, 0 }, 1, true);
} }
@ -255,13 +245,28 @@ namespace Ryujinx.Graphics.Vulkan
public unsafe void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) public unsafe void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)
{ {
// TODO: Use stencilMask (fully) // TODO: Use stencilMask (fully).
if (FramebufferParams == null || !FramebufferParams.HasDepthStencil) if (FramebufferParams == null || !FramebufferParams.HasDepthStencil)
{ {
return; return;
} }
var clearValue = new ClearValue(null, new ClearDepthStencilValue(depthValue, (uint)stencilValue));
var flags = depthMask ? ImageAspectFlags.DepthBit : 0;
if (stencilMask != 0)
{
flags |= ImageAspectFlags.StencilBit;
}
flags &= FramebufferParams.GetDepthStencilAspectFlags();
if (flags == ImageAspectFlags.None)
{
return;
}
if (_renderPass == null) if (_renderPass == null)
{ {
CreateRenderPass(); CreateRenderPass();
@ -269,14 +274,6 @@ namespace Ryujinx.Graphics.Vulkan
BeginRenderPass(); BeginRenderPass();
var clearValue = new ClearValue(null, new ClearDepthStencilValue(depthValue, (uint)stencilValue));
var flags = depthMask ? ImageAspectFlags.DepthBit : 0;
if (stencilMask != 0)
{
flags |= ImageAspectFlags.StencilBit;
}
var attachment = new ClearAttachment(flags, 0, clearValue); var attachment = new ClearAttachment(flags, 0, clearValue);
var clearRect = FramebufferParams.GetClearRect(ClearScissor, layer, layerCount); var clearRect = FramebufferParams.GetClearRect(ClearScissor, layer, layerCount);
@ -666,8 +663,6 @@ namespace Ryujinx.Graphics.Vulkan
{ {
if (texture is TextureView srcTexture) if (texture is TextureView srcTexture)
{ {
SupportBufferUpdater.Commit();
var oldCullMode = _newState.CullMode; var oldCullMode = _newState.CullMode;
var oldStencilTestEnable = _newState.StencilTestEnable; var oldStencilTestEnable = _newState.StencilTestEnable;
var oldDepthTestEnable = _newState.DepthTestEnable; var oldDepthTestEnable = _newState.DepthTestEnable;
@ -709,16 +704,6 @@ namespace Ryujinx.Graphics.Vulkan
_tfEnabled = false; _tfEnabled = false;
} }
public double GetCounterDivisor(CounterType type)
{
if (type == CounterType.SamplesPassed)
{
return _renderScale[0].X * _renderScale[0].X;
}
return 1;
}
public bool IsCommandBufferActive(CommandBuffer cb) public bool IsCommandBufferActive(CommandBuffer cb)
{ {
return CommandBuffer.Handle == cb.Handle; return CommandBuffer.Handle == cb.Handle;
@ -957,7 +942,7 @@ namespace Ryujinx.Graphics.Vulkan
SignalStateChange(); SignalStateChange();
if (_program.IsCompute) if (internalProgram.IsCompute)
{ {
EndRenderPass(); EndRenderPass();
} }
@ -1050,12 +1035,6 @@ namespace Ryujinx.Graphics.Vulkan
SetRenderTargetsInternal(colors, depthStencil, Gd.IsTBDR); SetRenderTargetsInternal(colors, depthStencil, Gd.IsTBDR);
} }
public void SetRenderTargetScale(float scale)
{
_renderScale[0].X = scale;
SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, 1); // Just the first element.
}
public void SetScissors(ReadOnlySpan<Rectangle<int>> regions) public void SetScissors(ReadOnlySpan<Rectangle<int>> regions)
{ {
int maxScissors = Gd.Capabilities.SupportsMultiView ? Constants.MaxViewports : 1; int maxScissors = Gd.Capabilities.SupportsMultiView ? Constants.MaxViewports : 1;
@ -1303,7 +1282,7 @@ namespace Ryujinx.Graphics.Vulkan
SignalStateChange(); SignalStateChange();
} }
public void SetViewports(ReadOnlySpan<Viewport> viewports, bool disableTransform) public void SetViewports(ReadOnlySpan<Viewport> viewports)
{ {
int maxViewports = Gd.Capabilities.SupportsMultiView ? Constants.MaxViewports : 1; int maxViewports = Gd.Capabilities.SupportsMultiView ? Constants.MaxViewports : 1;
int count = Math.Min(maxViewports, viewports.Length); int count = Math.Min(maxViewports, viewports.Length);
@ -1328,19 +1307,6 @@ namespace Ryujinx.Graphics.Vulkan
Clamp(viewport.DepthFar))); Clamp(viewport.DepthFar)));
} }
float disableTransformF = disableTransform ? 1.0f : 0.0f;
if (SupportBufferUpdater.Data.ViewportInverse.W != disableTransformF || disableTransform)
{
float scale = _renderScale[0].X;
SupportBufferUpdater.UpdateViewportInverse(new Vector4<float>
{
X = scale * 2f / viewports[0].Region.Width,
Y = scale * 2f / viewports[0].Region.Height,
Z = 1,
W = disableTransformF,
});
}
_newState.ViewportsCount = (uint)count; _newState.ViewportsCount = (uint)count;
SignalStateChange(); SignalStateChange();
} }
@ -1391,32 +1357,6 @@ namespace Ryujinx.Graphics.Vulkan
TextureBarrier(); TextureBarrier();
} }
public void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount)
{
bool changed = false;
for (int index = 0; index < totalCount; index++)
{
if (_renderScale[1 + index].X != scales[index])
{
_renderScale[1 + index].X = scales[index];
changed = true;
}
}
// Only update fragment count if there are scales after it for the vertex stage.
if (fragmentCount != totalCount && fragmentCount != _fragmentScaleCount)
{
_fragmentScaleCount = fragmentCount;
SupportBufferUpdater.UpdateFragmentRenderScaleCount(_fragmentScaleCount);
}
if (changed)
{
SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, 1 + totalCount);
}
}
protected void SignalCommandBufferChange() protected void SignalCommandBufferChange()
{ {
_needsIndexBufferRebind = true; _needsIndexBufferRebind = true;
@ -1614,9 +1554,6 @@ namespace Ryujinx.Graphics.Vulkan
DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer); DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
// Commit changes to the support buffer before drawing.
SupportBufferUpdater.Commit();
if (_needsIndexBufferRebind && _indexBufferPattern == null) if (_needsIndexBufferRebind && _indexBufferPattern == null)
{ {
_indexBuffer.BindIndexBuffer(Gd, Cbs); _indexBuffer.BindIndexBuffer(Gd, Cbs);
@ -1777,8 +1714,6 @@ namespace Ryujinx.Graphics.Vulkan
{ {
Gd.Api.DestroyPipelineCache(Device, PipelineCache, null); Gd.Api.DestroyPipelineCache(Device, PipelineCache, null);
} }
SupportBufferUpdater.Dispose();
} }
} }

View file

@ -130,7 +130,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
} }
} }
public CounterQueueEvent QueueReport(EventHandler<ulong> resultHandler, ulong lastDrawIndex, bool hostReserved) public CounterQueueEvent QueueReport(EventHandler<ulong> resultHandler, float divisor, ulong lastDrawIndex, bool hostReserved)
{ {
CounterQueueEvent result; CounterQueueEvent result;
ulong draws = lastDrawIndex - _current.DrawIndex; ulong draws = lastDrawIndex - _current.DrawIndex;
@ -146,7 +146,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
_current.ReserveForHostAccess(); _current.ReserveForHostAccess();
} }
_current.Complete(draws > 0 && Type != CounterType.TransformFeedbackPrimitivesWritten, _pipeline.GetCounterDivisor(Type)); _current.Complete(draws > 0 && Type != CounterType.TransformFeedbackPrimitivesWritten, divisor);
_events.Enqueue(_current); _events.Enqueue(_current);
_current.OnResult += resultHandler; _current.OnResult += resultHandler;

View file

@ -37,9 +37,9 @@ namespace Ryujinx.Graphics.Vulkan.Queries
_counterQueues[(int)CounterType.SamplesPassed].ResetFutureCounters(cmd, count); _counterQueues[(int)CounterType.SamplesPassed].ResetFutureCounters(cmd, count);
} }
public CounterQueueEvent QueueReport(CounterType type, EventHandler<ulong> resultHandler, bool hostReserved) public CounterQueueEvent QueueReport(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved)
{ {
return _counterQueues[(int)type].QueueReport(resultHandler, _pipeline.DrawCount, hostReserved); return _counterQueues[(int)type].QueueReport(resultHandler, divisor, _pipeline.DrawCount, hostReserved);
} }
public void QueueReset(CounterType type) public void QueueReset(CounterType type)

View file

@ -21,6 +21,31 @@
<EmbeddedResource Include="Effects\Shaders\SmaaBlend.spv" /> <EmbeddedResource Include="Effects\Shaders\SmaaBlend.spv" />
<EmbeddedResource Include="Effects\Shaders\SmaaEdge.spv" /> <EmbeddedResource Include="Effects\Shaders\SmaaEdge.spv" />
<EmbeddedResource Include="Effects\Shaders\SmaaNeighbour.spv" /> <EmbeddedResource Include="Effects\Shaders\SmaaNeighbour.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ChangeBufferStride.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorBlitClearAlphaFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorBlitFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorBlitMsFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorBlitVertex.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorClearFFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorClearSIFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorClearUIFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorClearVertex.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorCopyShorteningCompute.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorCopyToNonMsCompute.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorCopyWideningCompute.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorDrawToMsFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ColorDrawToMsVertex.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ConvertD32S8ToD24S8.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ConvertIndexBuffer.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\ConvertIndirectData.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\DepthBlitFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\DepthBlitMsFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\DepthDrawToMsFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\DepthDrawToNonMsFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\StencilBlitFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\StencilBlitMsFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\StencilDrawToMsFragment.spv" />
<EmbeddedResource Include="Shaders\SpirvBinaries\StencilDrawToNonMsFragment.spv" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

File diff suppressed because it is too large Load diff

View file

@ -25,15 +25,12 @@ namespace Ryujinx.Graphics.Vulkan
public VkFormat VkFormat { get; } public VkFormat VkFormat { get; }
public float ScaleFactor { get; } public TextureBuffer(VulkanRenderer gd, TextureCreateInfo info)
public TextureBuffer(VulkanRenderer gd, TextureCreateInfo info, float scale)
{ {
_gd = gd; _gd = gd;
Width = info.Width; Width = info.Width;
Height = info.Height; Height = info.Height;
VkFormat = FormatTable.GetFormat(info.Format); VkFormat = FormatTable.GetFormat(info.Format);
ScaleFactor = scale;
gd.Textures.Add(this); gd.Textures.Add(this);
} }

View file

@ -54,19 +54,16 @@ namespace Ryujinx.Graphics.Vulkan
private readonly ulong _size; private readonly ulong _size;
public VkFormat VkFormat { get; } public VkFormat VkFormat { get; }
public float ScaleFactor { get; }
public unsafe TextureStorage( public unsafe TextureStorage(
VulkanRenderer gd, VulkanRenderer gd,
Device device, Device device,
TextureCreateInfo info, TextureCreateInfo info,
float scaleFactor,
Auto<MemoryAllocation> foreignAllocation = null) Auto<MemoryAllocation> foreignAllocation = null)
{ {
_gd = gd; _gd = gd;
_device = device; _device = device;
_info = info; _info = info;
ScaleFactor = scaleFactor;
var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format); var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format);
var levels = (uint)info.Levels; var levels = (uint)info.Levels;
@ -81,7 +78,7 @@ namespace Ryujinx.Graphics.Vulkan
var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples); var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples);
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample); var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample, forceStorage: true);
var flags = ImageCreateFlags.CreateMutableFormatBit; var flags = ImageCreateFlags.CreateMutableFormatBit;
@ -175,7 +172,7 @@ namespace Ryujinx.Graphics.Vulkan
var info = NewCreateInfoWith(ref _info, format, _info.BytesPerPixel); var info = NewCreateInfoWith(ref _info, format, _info.BytesPerPixel);
storage = new TextureStorage(_gd, _device, info, ScaleFactor, _allocationAuto); storage = new TextureStorage(_gd, _device, info, _allocationAuto);
_aliasedStorages.Add(format, storage); _aliasedStorages.Add(format, storage);
} }
@ -294,7 +291,7 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
public static ImageUsageFlags GetImageUsage(Format format, Target target, bool supportsMsStorage) public static ImageUsageFlags GetImageUsage(Format format, Target target, bool supportsMsStorage, bool forceStorage = false)
{ {
var usage = DefaultUsageFlags; var usage = DefaultUsageFlags;
@ -307,7 +304,7 @@ namespace Ryujinx.Graphics.Vulkan
usage |= ImageUsageFlags.ColorAttachmentBit; usage |= ImageUsageFlags.ColorAttachmentBit;
} }
if (format.IsImageCompatible() && (supportsMsStorage || !target.IsMultisample())) if (((forceStorage && !format.IsDepthOrStencil()) || format.IsImageCompatible()) && (supportsMsStorage || !target.IsMultisample()))
{ {
usage |= ImageUsageFlags.StorageBit; usage |= ImageUsageFlags.StorageBit;
} }

View file

@ -32,7 +32,6 @@ namespace Ryujinx.Graphics.Vulkan
public int Layers => Info.GetDepthOrLayers(); public int Layers => Info.GetDepthOrLayers();
public int FirstLayer { get; } public int FirstLayer { get; }
public int FirstLevel { get; } public int FirstLevel { get; }
public float ScaleFactor => Storage.ScaleFactor;
public VkFormat VkFormat { get; } public VkFormat VkFormat { get; }
public bool Valid { get; private set; } public bool Valid { get; private set; }
@ -117,7 +116,14 @@ namespace Ryujinx.Graphics.Vulkan
return new Auto<DisposableImageView>(new DisposableImageView(gd.Api, device, imageView), null, storage.GetImage()); return new Auto<DisposableImageView>(new DisposableImageView(gd.Api, device, imageView), null, storage.GetImage());
} }
_imageView = CreateImageView(componentMapping, subresourceRange, type, ImageUsageFlags.SampledBit); ImageUsageFlags shaderUsage = ImageUsageFlags.SampledBit;
if (info.Format.IsImageCompatible())
{
shaderUsage |= ImageUsageFlags.StorageBit;
}
_imageView = CreateImageView(componentMapping, subresourceRange, type, shaderUsage);
// Framebuffer attachments and storage images requires a identity component mapping. // Framebuffer attachments and storage images requires a identity component mapping.
var identityComponentMapping = new ComponentMapping( var identityComponentMapping = new ComponentMapping(
@ -379,7 +385,7 @@ namespace Ryujinx.Graphics.Vulkan
bool isDepthOrStencil = dst.Info.Format.IsDepthOrStencil(); bool isDepthOrStencil = dst.Info.Format.IsDepthOrStencil();
if (VulkanConfiguration.UseSlowSafeBlitOnAmd && (_gd.Vendor == Vendor.Amd || _gd.IsMoltenVk)) if (!VulkanConfiguration.UseUnsafeBlit || (_gd.Vendor != Vendor.Nvidia && _gd.Vendor != Vendor.Intel))
{ {
_gd.HelperShader.Blit( _gd.HelperShader.Blit(
_gd, _gd,

View file

@ -3,7 +3,7 @@
static class VulkanConfiguration static class VulkanConfiguration
{ {
public const bool UseFastBufferUpdates = true; public const bool UseFastBufferUpdates = true;
public const bool UseSlowSafeBlitOnAmd = true; public const bool UseUnsafeBlit = true;
public const bool UsePushDescriptors = false; public const bool UsePushDescriptors = false;
public const bool ForceD24S8Unsupported = false; public const bool ForceD24S8Unsupported = false;

View file

@ -10,17 +10,6 @@ namespace Ryujinx.Graphics.Vulkan
{ {
class VulkanDebugMessenger : IDisposable class VulkanDebugMessenger : IDisposable
{ {
private static readonly string[] _excludedMessages = {
// NOTE: Done on purpose right now.
"UNASSIGNED-CoreValidation-Shader-OutputNotConsumed",
// TODO: Figure out if fixable
"VUID-vkCmdDrawIndexed-None-04584",
// TODO: Might be worth looking into making this happy to possibly optimize copies.
"UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout",
// TODO: Fix this, it's causing too much noise right now.
"VUID-VkSubpassDependency-srcSubpass-00867",
};
private readonly Vk _api; private readonly Vk _api;
private readonly Instance _instance; private readonly Instance _instance;
private readonly GraphicsDebugLevel _logLevel; private readonly GraphicsDebugLevel _logLevel;
@ -108,14 +97,6 @@ namespace Ryujinx.Graphics.Vulkan
{ {
var msg = Marshal.PtrToStringAnsi((IntPtr)pCallbackData->PMessage); var msg = Marshal.PtrToStringAnsi((IntPtr)pCallbackData->PMessage);
foreach (string excludedMessagePart in _excludedMessages)
{
if (msg.Contains(excludedMessagePart))
{
return 0;
}
}
if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.ErrorBitExt)) if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.ErrorBitExt))
{ {
Logger.Error?.Print(LogClass.Gpu, msg); Logger.Error?.Print(LogClass.Gpu, msg);

View file

@ -377,8 +377,8 @@ namespace Ryujinx.Graphics.Vulkan
ShaderFloat64 = supportedFeatures.ShaderFloat64, ShaderFloat64 = supportedFeatures.ShaderFloat64,
ShaderImageGatherExtended = supportedFeatures.ShaderImageGatherExtended, ShaderImageGatherExtended = supportedFeatures.ShaderImageGatherExtended,
ShaderStorageImageMultisample = supportedFeatures.ShaderStorageImageMultisample, ShaderStorageImageMultisample = supportedFeatures.ShaderStorageImageMultisample,
// ShaderStorageImageReadWithoutFormat = true, ShaderStorageImageReadWithoutFormat = supportedFeatures.ShaderStorageImageReadWithoutFormat,
// ShaderStorageImageWriteWithoutFormat = true, ShaderStorageImageWriteWithoutFormat = supportedFeatures.ShaderStorageImageWriteWithoutFormat,
TessellationShader = supportedFeatures.TessellationShader, TessellationShader = supportedFeatures.TessellationShader,
VertexPipelineStoresAndAtomics = supportedFeatures.VertexPipelineStoresAndAtomics, VertexPipelineStoresAndAtomics = supportedFeatures.VertexPipelineStoresAndAtomics,
RobustBufferAccess = useRobustBufferAccess, RobustBufferAccess = useRobustBufferAccess,

View file

@ -432,26 +432,26 @@ namespace Ryujinx.Graphics.Vulkan
return new SamplerHolder(this, _device, info); return new SamplerHolder(this, _device, info);
} }
public ITexture CreateTexture(TextureCreateInfo info, float scale) public ITexture CreateTexture(TextureCreateInfo info)
{ {
if (info.Target == Target.TextureBuffer) if (info.Target == Target.TextureBuffer)
{ {
return new TextureBuffer(this, info, scale); return new TextureBuffer(this, info);
} }
return CreateTextureView(info, scale); return CreateTextureView(info);
} }
internal TextureView CreateTextureView(TextureCreateInfo info, float scale) internal TextureView CreateTextureView(TextureCreateInfo info)
{ {
// This should be disposed when all views are destroyed. // This should be disposed when all views are destroyed.
var storage = CreateTextureStorage(info, scale); var storage = CreateTextureStorage(info);
return storage.CreateView(info, 0, 0); return storage.CreateView(info, 0, 0);
} }
internal TextureStorage CreateTextureStorage(TextureCreateInfo info, float scale) internal TextureStorage CreateTextureStorage(TextureCreateInfo info)
{ {
return new TextureStorage(this, _device, info, scale); return new TextureStorage(this, _device, info);
} }
public void DeleteBuffer(BufferHandle buffer) public void DeleteBuffer(BufferHandle buffer)
@ -753,9 +753,9 @@ namespace Ryujinx.Graphics.Vulkan
SyncManager.Cleanup(); SyncManager.Cleanup();
} }
public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, bool hostReserved) public ICounterEvent ReportCounter(CounterType type, EventHandler<ulong> resultHandler, float divisor, bool hostReserved)
{ {
return _counters.QueueReport(type, resultHandler, hostReserved); return _counters.QueueReport(type, resultHandler, divisor, hostReserved);
} }
public void ResetCounter(CounterType type) public void ResetCounter(CounterType type)

View file

@ -294,12 +294,11 @@ namespace Ryujinx.Graphics.Vulkan
} }
int srcX0, srcX1, srcY0, srcY1; int srcX0, srcX1, srcY0, srcY1;
float scale = view.ScaleFactor;
if (crop.Left == 0 && crop.Right == 0) if (crop.Left == 0 && crop.Right == 0)
{ {
srcX0 = 0; srcX0 = 0;
srcX1 = (int)(view.Width / scale); srcX1 = view.Width;
} }
else else
{ {
@ -310,7 +309,7 @@ namespace Ryujinx.Graphics.Vulkan
if (crop.Top == 0 && crop.Bottom == 0) if (crop.Top == 0 && crop.Bottom == 0)
{ {
srcY0 = 0; srcY0 = 0;
srcY1 = (int)(view.Height / scale); srcY1 = view.Height;
} }
else else
{ {
@ -318,14 +317,6 @@ namespace Ryujinx.Graphics.Vulkan
srcY1 = crop.Bottom; srcY1 = crop.Bottom;
} }
if (scale != 1f)
{
srcX0 = (int)(srcX0 * scale);
srcY0 = (int)(srcY0 * scale);
srcX1 = (int)Math.Ceiling(srcX1 * scale);
srcY1 = (int)Math.Ceiling(srcY1 * scale);
}
if (ScreenCaptureRequested) if (ScreenCaptureRequested)
{ {
if (_effect != null) if (_effect != null)