Add per-source type memory change tracking, simplified state change tracking, other fixes

This commit is contained in:
gdk 2019-10-26 14:50:52 -03:00 committed by Thog
parent 1b7d955195
commit 8cba252b23
40 changed files with 494 additions and 668 deletions

View file

@ -14,8 +14,6 @@ namespace ARMeilleure.Memory
public const int PageSize = 1 << PageBits; public const int PageSize = 1 << PageBits;
public const int PageMask = PageSize - 1; public const int PageMask = PageSize - 1;
private const long PteFlagNotModified = 1;
internal const long PteFlagsMask = 7; internal const long PteFlagsMask = 7;
public IntPtr Ram { get; private set; } public IntPtr Ram { get; private set; }
@ -106,6 +104,11 @@ namespace ARMeilleure.Memory
ptr = (byte*)ptrUlong; ptr = (byte*)ptrUlong;
} }
if (ptr == null)
{
return IntPtr.Zero;
}
return new IntPtr(ptr + (position & PageMask)); return new IntPtr(ptr + (position & PageMask));
} }
@ -122,10 +125,7 @@ namespace ARMeilleure.Memory
if ((ptrUlong & PteFlagsMask) != 0) if ((ptrUlong & PteFlagsMask) != 0)
{ {
if ((ptrUlong & PteFlagNotModified) != 0) ClearPtEntryFlag(position, PteFlagsMask);
{
ClearPtEntryFlag(position, PteFlagNotModified);
}
ptrUlong &= ~(ulong)PteFlagsMask; ptrUlong &= ~(ulong)PteFlagsMask;
@ -253,8 +253,10 @@ namespace ARMeilleure.Memory
return ptePtr; return ptePtr;
} }
public unsafe (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size) public unsafe (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size, int id)
{ {
ulong idMask = 1UL << id;
List<(ulong, ulong)> ranges = new List<(ulong, ulong)>(); List<(ulong, ulong)> ranges = new List<(ulong, ulong)>();
ulong endAddress = (address + size + PageMask) & ~(ulong)PageMask; ulong endAddress = (address + size + PageMask) & ~(ulong)PageMask;
@ -272,12 +274,12 @@ namespace ARMeilleure.Memory
ulong ptrUlong = (ulong)ptr; ulong ptrUlong = (ulong)ptr;
if ((ptrUlong & PteFlagNotModified) == 0) if ((ptrUlong & idMask) == 0)
{ {
// Modified. // Modified.
currSize += PageSize; currSize += PageSize;
SetPtEntryFlag((long)address, PteFlagNotModified); SetPtEntryFlag((long)address, (long)idMask);
} }
else else
{ {

View file

@ -27,15 +27,15 @@ namespace Ryujinx.Graphics.Gpu.Engine
_context.Renderer.Pipeline.BindProgram(cs.Interface); _context.Renderer.Pipeline.BindProgram(cs.Interface);
PoolState samplerPool = _context.State.GetSamplerPoolState(); var samplerPool = _context.State.Get<PoolState>(MethodOffset.SamplerPoolState);
_textureManager.SetComputeSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId); _textureManager.SetComputeSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId);
PoolState texturePool = _context.State.GetTexturePoolState(); var texturePool = _context.State.Get<PoolState>(MethodOffset.TexturePoolState);
_textureManager.SetComputeTexturePool(texturePool.Address.Pack(), texturePool.MaximumId); _textureManager.SetComputeTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);
_textureManager.SetComputeTextureBufferIndex(_context.State.GetTextureBufferIndex()); _textureManager.SetComputeTextureBufferIndex(_context.State.Get<int>(MethodOffset.TextureBufferIndex));
ShaderProgramInfo info = cs.Shader.Info; ShaderProgramInfo info = cs.Shader.Info;
@ -117,6 +117,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
dispatchParams.UnpackGridSizeX(), dispatchParams.UnpackGridSizeX(),
dispatchParams.UnpackGridSizeY(), dispatchParams.UnpackGridSizeY(),
dispatchParams.UnpackGridSizeZ()); dispatchParams.UnpackGridSizeZ());
UpdateShaderState();
} }
} }
} }

View file

@ -12,9 +12,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
private int _offset; private int _offset;
private int _size; private int _size;
public void Execute(int argument) public void LaunchDma(int argument)
{ {
_params = _context.State.Get<Inline2MemoryParams>(MethodOffset.Inline2MemoryParams); _params = _context.State.Get<Inline2MemoryParams>(MethodOffset.I2mParams);
_isLinear = (argument & 1) != 0; _isLinear = (argument & 1) != 0;
@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
_size = _params.LineLengthIn * _params.LineCount; _size = _params.LineLengthIn * _params.LineCount;
} }
public void PushData(int argument) public void LoadInlineData(int argument)
{ {
if (_isLinear) if (_isLinear)
{ {

View file

@ -7,7 +7,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
private void Clear(int argument) private void Clear(int argument)
{ {
UpdateState(); UpdateRenderTargetStateIfNeeded();
_textureManager.CommitGraphicsBindings();
bool clearDepth = (argument & 1) != 0; bool clearDepth = (argument & 1) != 0;
bool clearStencil = (argument & 2) != 0; bool clearStencil = (argument & 2) != 0;
@ -18,7 +20,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
if (componentMask != 0) if (componentMask != 0)
{ {
ClearColors clearColor = _context.State.GetClearColors(); var clearColor = _context.State.Get<ClearColors>(MethodOffset.ClearColors);
ColorF color = new ColorF( ColorF color = new ColorF(
clearColor.Red, clearColor.Red,
@ -26,22 +28,19 @@ namespace Ryujinx.Graphics.Gpu.Engine
clearColor.Blue, clearColor.Blue,
clearColor.Alpha); clearColor.Alpha);
_context.Renderer.Pipeline.ClearRenderTargetColor( _context.Renderer.Pipeline.ClearRenderTargetColor(index, componentMask, color);
index,
componentMask,
color);
} }
if (clearDepth || clearStencil) if (clearDepth || clearStencil)
{ {
float depthValue = _context.State.GetClearDepthValue(); float depthValue = _context.State.Get<float>(MethodOffset.ClearDepthValue);
int stencilValue = _context.State.GetClearStencilValue(); int stencilValue = _context.State.Get<int> (MethodOffset.ClearStencilValue);
int stencilMask = 0; int stencilMask = 0;
if (clearStencil) if (clearStencil)
{ {
stencilMask = _context.State.GetStencilTestState().FrontMask; stencilMask = _context.State.Get<StencilTestState>(MethodOffset.StencilTestState).FrontMask;
} }
_context.Renderer.Pipeline.ClearRenderTargetDepthStencil( _context.Renderer.Pipeline.ClearRenderTargetDepthStencil(

View file

@ -7,8 +7,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
private void CopyTexture(int argument) private void CopyTexture(int argument)
{ {
CopyTexture dstCopyTexture = _context.State.GetCopyDstTexture(); var dstCopyTexture = _context.State.Get<CopyTexture>(MethodOffset.CopyDstTexture);
CopyTexture srcCopyTexture = _context.State.GetCopySrcTexture(); var srcCopyTexture = _context.State.Get<CopyTexture>(MethodOffset.CopySrcTexture);
Image.Texture srcTexture = _textureManager.FindOrCreateTexture(srcCopyTexture); Image.Texture srcTexture = _textureManager.FindOrCreateTexture(srcCopyTexture);
@ -32,9 +32,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
return; return;
} }
CopyTextureControl control = _context.State.GetCopyTextureControl(); var control = _context.State.Get<CopyTextureControl>(MethodOffset.CopyTextureControl);
CopyRegion region = _context.State.GetCopyRegion(); var region = _context.State.Get<CopyRegion>(MethodOffset.CopyRegion);
int srcX1 = (int)(region.SrcXF >> 32); int srcX1 = (int)(region.SrcXF >> 32);
int srcY1 = (int)(region.SrcYF >> 32); int srcY1 = (int)(region.SrcYF >> 32);

View file

@ -39,12 +39,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
_instancedIndexed = _drawIndexed; _instancedIndexed = _drawIndexed;
_instancedFirstIndex = _firstIndex; _instancedFirstIndex = _firstIndex;
_instancedFirstVertex = _context.State.GetBaseVertex(); _instancedFirstVertex = _context.State.Get<int>(MethodOffset.FirstVertex);
_instancedFirstInstance = _context.State.GetBaseInstance(); _instancedFirstInstance = _context.State.Get<int>(MethodOffset.FirstInstance);
_instancedIndexCount = _indexCount; _instancedIndexCount = _indexCount;
VertexBufferDrawState drawState = _context.State.GetVertexBufferDrawState(); var drawState = _context.State.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
_instancedDrawStateFirst = drawState.First; _instancedDrawStateFirst = drawState.First;
_instancedDrawStateCount = drawState.Count; _instancedDrawStateCount = drawState.Count;
@ -53,13 +53,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
return; return;
} }
int firstInstance = _context.State.GetBaseInstance(); int firstInstance = _context.State.Get<int>(MethodOffset.FirstInstance);
if (_drawIndexed) if (_drawIndexed)
{ {
_drawIndexed = false; _drawIndexed = false;
int firstVertex = _context.State.GetBaseVertex(); int firstVertex = _context.State.Get<int>(MethodOffset.FirstVertex);
_context.Renderer.Pipeline.DrawIndexed( _context.Renderer.Pipeline.DrawIndexed(
_indexCount, _indexCount,
@ -70,7 +70,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
} }
else else
{ {
VertexBufferDrawState drawState = _context.State.GetVertexBufferDrawState(); var drawState = _context.State.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
_context.Renderer.Pipeline.Draw( _context.Renderer.Pipeline.Draw(
drawState.Count, drawState.Count,
@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
} }
} }
private void SetIndexCount(int argument) private void SetIndexBufferCount(int argument)
{ {
_drawIndexed = true; _drawIndexed = true;
} }

View file

@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
private void ReportSemaphore() private void ReportSemaphore()
{ {
ReportState state = _context.State.GetReportState(); var state = _context.State.Get<ReportState>(MethodOffset.ReportState);
_context.MemoryAccessor.Write(state.Address.Pack(), state.Payload); _context.MemoryAccessor.Write(state.Address.Pack(), state.Payload);
@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
Span<byte> data = MemoryMarshal.Cast<CounterData, byte>(counterDataSpan); Span<byte> data = MemoryMarshal.Cast<CounterData, byte>(counterDataSpan);
ReportState state = _context.State.GetReportState(); var state = _context.State.Get<ReportState>(MethodOffset.ReportState);
_context.MemoryAccessor.Write(state.Address.Pack(), data); _context.MemoryAccessor.Write(state.Address.Pack(), data);
} }

View file

@ -4,27 +4,27 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
partial class Methods partial class Methods
{ {
private void UniformBufferBind0(int argument) private void UniformBufferBindVertex(int argument)
{ {
UniformBufferBind(argument, ShaderType.Vertex); UniformBufferBind(argument, ShaderType.Vertex);
} }
private void UniformBufferBind1(int argument) private void UniformBufferBindTessControl(int argument)
{ {
UniformBufferBind(argument, ShaderType.TessellationControl); UniformBufferBind(argument, ShaderType.TessellationControl);
} }
private void UniformBufferBind2(int argument) private void UniformBufferBindTessEvaluation(int argument)
{ {
UniformBufferBind(argument, ShaderType.TessellationEvaluation); UniformBufferBind(argument, ShaderType.TessellationEvaluation);
} }
private void UniformBufferBind3(int argument) private void UniformBufferBindGeometry(int argument)
{ {
UniformBufferBind(argument, ShaderType.Geometry); UniformBufferBind(argument, ShaderType.Geometry);
} }
private void UniformBufferBind4(int argument) private void UniformBufferBindFragment(int argument)
{ {
UniformBufferBind(argument, ShaderType.Fragment); UniformBufferBind(argument, ShaderType.Fragment);
} }
@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
if (enable) if (enable)
{ {
UniformBufferState uniformBuffer = _context.State.GetUniformBufferState(); var uniformBuffer = _context.State.Get<UniformBufferState>(MethodOffset.UniformBufferState);
ulong address = uniformBuffer.Address.Pack(); ulong address = uniformBuffer.Address.Pack();

View file

@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
private void UniformBufferUpdate(int argument) private void UniformBufferUpdate(int argument)
{ {
UniformBufferState uniformBuffer = _context.State.GetUniformBufferState(); var uniformBuffer = _context.State.Get<UniformBufferState>(MethodOffset.UniformBufferState);
_context.MemoryAccessor.Write(uniformBuffer.Address.Pack() + (uint)uniformBuffer.Offset, argument); _context.MemoryAccessor.Write(uniformBuffer.Address.Pack() + (uint)uniformBuffer.Offset, argument);

View file

@ -18,6 +18,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
private ShaderCache _shaderCache; private ShaderCache _shaderCache;
private ShaderProgramInfo[] _currentProgramInfo;
private BufferManager _bufferManager; private BufferManager _bufferManager;
private TextureManager _textureManager; private TextureManager _textureManager;
@ -33,6 +35,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
_shaderCache = new ShaderCache(_context); _shaderCache = new ShaderCache(_context);
_currentProgramInfo = new ShaderProgramInfo[Constants.TotalShaderStages];
_bufferManager = new BufferManager(context); _bufferManager = new BufferManager(context);
_textureManager = new TextureManager(context); _textureManager = new TextureManager(context);
@ -41,128 +45,184 @@ namespace Ryujinx.Graphics.Gpu.Engine
private void RegisterCallbacks() private void RegisterCallbacks()
{ {
_context.State.RegisterCopyBufferCallback(CopyBuffer); _context.State.RegisterCallback(MethodOffset.LaunchDma, LaunchDma);
_context.State.RegisterCopyTextureCallback(CopyTexture); _context.State.RegisterCallback(MethodOffset.LoadInlineData, LoadInlineData);
_context.State.RegisterDrawEndCallback(DrawEnd); _context.State.RegisterCallback(MethodOffset.Dispatch, Dispatch);
_context.State.RegisterDrawBeginCallback(DrawBegin); _context.State.RegisterCallback(MethodOffset.CopyBuffer, CopyBuffer);
_context.State.RegisterCallback(MethodOffset.CopyTexture, CopyTexture);
_context.State.RegisterSetIndexCountCallback(SetIndexCount);
_context.State.RegisterClearCallback(Clear);
_context.State.RegisterReportCallback(Report);
_context.State.RegisterUniformBufferUpdateCallback(UniformBufferUpdate);
_context.State.RegisterUniformBufferBind0Callback(UniformBufferBind0);
_context.State.RegisterUniformBufferBind1Callback(UniformBufferBind1);
_context.State.RegisterUniformBufferBind2Callback(UniformBufferBind2);
_context.State.RegisterUniformBufferBind3Callback(UniformBufferBind3);
_context.State.RegisterUniformBufferBind4Callback(UniformBufferBind4);
_context.State.RegisterCallback(MethodOffset.TextureBarrier, TextureBarrier); _context.State.RegisterCallback(MethodOffset.TextureBarrier, TextureBarrier);
_context.State.RegisterCallback(MethodOffset.InvalidateTextures, InvalidateTextures); _context.State.RegisterCallback(MethodOffset.InvalidateTextures, InvalidateTextures);
_context.State.RegisterCallback(MethodOffset.TextureBarrierTiled, TextureBarrierTiled); _context.State.RegisterCallback(MethodOffset.TextureBarrierTiled, TextureBarrierTiled);
_context.State.RegisterCallback(MethodOffset.ResetCounter, ResetCounter); _context.State.RegisterCallback(MethodOffset.ResetCounter, ResetCounter);
_context.State.RegisterCallback(MethodOffset.Inline2MemoryExecute, Execute); _context.State.RegisterCallback(MethodOffset.DrawEnd, DrawEnd);
_context.State.RegisterCallback(MethodOffset.Inline2MemoryPushData, PushData); _context.State.RegisterCallback(MethodOffset.DrawBegin, DrawBegin);
_context.State.RegisterCallback(MethodOffset.Dispatch, Dispatch); _context.State.RegisterCallback(MethodOffset.IndexBufferCount, SetIndexBufferCount);
_context.State.RegisterCallback(MethodOffset.Clear, Clear);
_context.State.RegisterCallback(MethodOffset.Report, Report);
_context.State.RegisterCallback(MethodOffset.UniformBufferUpdateData, 16, UniformBufferUpdate);
_context.State.RegisterCallback(MethodOffset.UniformBufferBindVertex, UniformBufferBindVertex);
_context.State.RegisterCallback(MethodOffset.UniformBufferBindTessControl, UniformBufferBindTessControl);
_context.State.RegisterCallback(MethodOffset.UniformBufferBindTessEvaluation, UniformBufferBindTessEvaluation);
_context.State.RegisterCallback(MethodOffset.UniformBufferBindGeometry, UniformBufferBindGeometry);
_context.State.RegisterCallback(MethodOffset.UniformBufferBindFragment, UniformBufferBindFragment);
} }
public Image.Texture GetTexture(ulong address) => _textureManager.Find2(address); public Image.Texture GetTexture(ulong address) => _textureManager.Find2(address);
private void UpdateState() private void UpdateState()
{ {
if ((_context.State.StateWriteFlags & StateWriteFlags.Any) == 0)
{
CommitBindings();
return;
}
// Shaders must be the first one to be updated if modified, because // Shaders must be the first one to be updated if modified, because
// some of the other state depends on information from the currently // some of the other state depends on information from the currently
// bound shaders. // bound shaders.
if ((_context.State.StateWriteFlags & StateWriteFlags.ShaderState) != 0) if (_context.State.QueryModified(MethodOffset.ShaderBaseAddress, MethodOffset.ShaderState))
{ {
UpdateShaderState(); UpdateShaderState();
} }
if ((_context.State.StateWriteFlags & StateWriteFlags.RenderTargetGroup) != 0) UpdateRenderTargetStateIfNeeded();
{
UpdateRenderTargetGroupState();
}
if ((_context.State.StateWriteFlags & StateWriteFlags.DepthTestState) != 0) if (_context.State.QueryModified(MethodOffset.DepthTestEnable,
MethodOffset.DepthWriteEnable,
MethodOffset.DepthTestFunc))
{ {
UpdateDepthTestState(); UpdateDepthTestState();
} }
if ((_context.State.StateWriteFlags & StateWriteFlags.ViewportTransform) != 0) if (_context.State.QueryModified(MethodOffset.ViewportTransform, MethodOffset.ViewportExtents))
{ {
UpdateViewportTransform(); UpdateViewportTransform();
} }
if ((_context.State.StateWriteFlags & StateWriteFlags.DepthBiasState) != 0) if (_context.State.QueryModified(MethodOffset.DepthBiasState,
MethodOffset.DepthBiasFactor,
MethodOffset.DepthBiasUnits,
MethodOffset.DepthBiasClamp))
{ {
UpdateDepthBiasState(); UpdateDepthBiasState();
} }
if ((_context.State.StateWriteFlags & StateWriteFlags.StencilTestState) != 0) if (_context.State.QueryModified(MethodOffset.StencilBackMasks,
MethodOffset.StencilTestState,
MethodOffset.StencilBackTestState))
{ {
UpdateStencilTestState(); UpdateStencilTestState();
} }
if ((_context.State.StateWriteFlags & StateWriteFlags.SamplerPoolState) != 0) // Pools.
if (_context.State.QueryModified(MethodOffset.SamplerPoolState))
{ {
UpdateSamplerPoolState(); UpdateSamplerPoolState();
} }
if ((_context.State.StateWriteFlags & StateWriteFlags.TexturePoolState) != 0) if (_context.State.QueryModified(MethodOffset.TexturePoolState))
{ {
UpdateTexturePoolState(); UpdateTexturePoolState();
} }
if ((_context.State.StateWriteFlags & StateWriteFlags.InputAssemblerGroup) != 0) // Input assembler state.
if (_context.State.QueryModified(MethodOffset.VertexAttribState))
{ {
UpdateInputAssemblerGroupState(); UpdateVertexAttribState();
} }
if ((_context.State.StateWriteFlags & StateWriteFlags.FaceState) != 0) if (_context.State.QueryModified(MethodOffset.PrimitiveRestartState))
{
UpdatePrimitiveRestartState();
}
if (_context.State.QueryModified(MethodOffset.IndexBufferState))
{
UpdateIndexBufferState();
}
if (_context.State.QueryModified(MethodOffset.VertexBufferDrawState,
MethodOffset.VertexBufferInstanced,
MethodOffset.VertexBufferState,
MethodOffset.VertexBufferEndAddress))
{
UpdateVertexBufferState();
}
if (_context.State.QueryModified(MethodOffset.FaceState))
{ {
UpdateFaceState(); UpdateFaceState();
} }
if ((_context.State.StateWriteFlags & StateWriteFlags.RtColorMask) != 0) if (_context.State.QueryModified(MethodOffset.RtColorMask))
{ {
UpdateRtColorMask(); UpdateRtColorMask();
} }
if ((_context.State.StateWriteFlags & StateWriteFlags.BlendState) != 0) if (_context.State.QueryModified(MethodOffset.BlendEnable, MethodOffset.BlendState))
{ {
UpdateBlendState(); UpdateBlendState();
} }
_context.State.StateWriteFlags &= ~StateWriteFlags.Any;
CommitBindings(); CommitBindings();
} }
private void CommitBindings() private void CommitBindings()
{ {
UpdateStorageBuffers();
_bufferManager.CommitBindings(); _bufferManager.CommitBindings();
_textureManager.CommitGraphicsBindings(); _textureManager.CommitGraphicsBindings();
} }
private void UpdateRenderTargetGroupState() private void UpdateStorageBuffers()
{ {
TextureMsaaMode msaaMode = _context.State.GetRtMsaaMode(); for (int stage = 0; stage < _currentProgramInfo.Length; stage++)
{
ShaderProgramInfo info = _currentProgramInfo[stage];
if (info == null)
{
continue;
}
for (int index = 0; index < info.SBuffers.Count; index++)
{
BufferDescriptor sb = info.SBuffers[index];
ulong sbDescAddress = _bufferManager.GetGraphicsUniformBufferAddress(stage, 0);
int sbDescOffset = 0x110 + stage * 0x100 + sb.Slot * 0x10;
sbDescAddress += (ulong)sbDescOffset;
Span<byte> sbDescriptorData = _context.PhysicalMemory.Read(sbDescAddress, 0x10);
SbDescriptor sbDescriptor = MemoryMarshal.Cast<byte, SbDescriptor>(sbDescriptorData)[0];
_bufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size);
}
}
}
private void UpdateRenderTargetStateIfNeeded()
{
if (_context.State.QueryModified(MethodOffset.RtColorState,
MethodOffset.RtDepthStencilState,
MethodOffset.RtDepthStencilSize,
MethodOffset.RtDepthStencilEnable))
{
UpdateRenderTargetState();
}
}
private void UpdateRenderTargetState()
{
var msaaMode = _context.State.Get<TextureMsaaMode>(MethodOffset.RtMsaaMode);
int samplesInX = msaaMode.SamplesInX(); int samplesInX = msaaMode.SamplesInX();
int samplesInY = msaaMode.SamplesInY(); int samplesInY = msaaMode.SamplesInY();
@ -173,7 +233,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
for (int index = 0; index < Constants.TotalRenderTargets; index++) for (int index = 0; index < Constants.TotalRenderTargets; index++)
{ {
RtColorState colorState = _context.State.GetRtColorState(index); var colorState = _context.State.Get<RtColorState>(MethodOffset.RtColorState, index);
if (!IsRtEnabled(colorState)) if (!IsRtEnabled(colorState))
{ {
@ -189,9 +249,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
_textureManager.SetRenderTargetColor(index, color); _textureManager.SetRenderTargetColor(index, color);
if (color != null)
{
color.Modified = true; color.Modified = true;
} }
} }
}
else else
{ {
_textureManager.SetRenderTargetColor3D(color3D); _textureManager.SetRenderTargetColor3D(color3D);
@ -199,14 +262,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
color3D.Modified = true; color3D.Modified = true;
} }
bool dsEnable = _context.State.Get<bool>(MethodOffset.RtDepthStencilEnable); bool dsEnable = _context.State.Get<Boolean32>(MethodOffset.RtDepthStencilEnable);
Image.Texture depthStencil = null; Image.Texture depthStencil = null;
if (dsEnable) if (dsEnable)
{ {
var dsState = _context.State.GetRtDepthStencilState(); var dsState = _context.State.Get<RtDepthStencilState>(MethodOffset.RtDepthStencilState);
var dsSize = _context.State.GetRtDepthStencilSize(); var dsSize = _context.State.Get<Size3D> (MethodOffset.RtDepthStencilSize);
depthStencil = _textureManager.FindOrCreateTexture( depthStencil = _textureManager.FindOrCreateTexture(
dsState, dsState,
@ -216,11 +279,16 @@ namespace Ryujinx.Graphics.Gpu.Engine
} }
_textureManager.SetRenderTargetDepthStencil(depthStencil); _textureManager.SetRenderTargetDepthStencil(depthStencil);
if (depthStencil != null)
{
depthStencil.Modified = true;
}
} }
private Image.Texture Get3DRenderTarget(int samplesInX, int samplesInY) private Image.Texture Get3DRenderTarget(int samplesInX, int samplesInY)
{ {
RtColorState colorState0 = _context.State.GetRtColorState(0); var colorState0 = _context.State.Get<RtColorState>(MethodOffset.RtColorState, 0);
if (!IsRtEnabled(colorState0) || !colorState0.MemoryLayout.UnpackIsTarget3D() || colorState0.Depth != 1) if (!IsRtEnabled(colorState0) || !colorState0.MemoryLayout.UnpackIsTarget3D() || colorState0.Depth != 1)
{ {
@ -232,7 +300,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
for (int index = 1; index < Constants.TotalRenderTargets; index++) for (int index = 1; index < Constants.TotalRenderTargets; index++)
{ {
RtColorState colorState = _context.State.GetRtColorState(index); var colorState = _context.State.Get<RtColorState>(MethodOffset.RtColorState, index);
if (!IsRtEnabled(colorState)) if (!IsRtEnabled(colorState))
{ {
@ -266,9 +334,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
private void UpdateDepthTestState() private void UpdateDepthTestState()
{ {
_context.Renderer.Pipeline.SetDepthTest(new DepthTestDescriptor( _context.Renderer.Pipeline.SetDepthTest(new DepthTestDescriptor(
_context.State.GetDepthTestEnable().IsTrue(), _context.State.Get<Boolean32>(MethodOffset.DepthTestEnable),
_context.State.GetDepthWriteEnable().IsTrue(), _context.State.Get<Boolean32>(MethodOffset.DepthWriteEnable),
_context.State.GetDepthTestFunc())); _context.State.Get<CompareOp>(MethodOffset.DepthTestFunc)));
} }
private void UpdateViewportTransform() private void UpdateViewportTransform()
@ -277,8 +345,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
for (int index = 0; index < Constants.TotalViewports; index++) for (int index = 0; index < Constants.TotalViewports; index++)
{ {
var transform = _context.State.Get<ViewportTransform>(MethodOffset.ViewportTransform + index * 8); var transform = _context.State.Get<ViewportTransform>(MethodOffset.ViewportTransform, index);
var extents = _context.State.Get<ViewportExtents> (MethodOffset.ViewportExtents + index * 4); var extents = _context.State.Get<ViewportExtents> (MethodOffset.ViewportExtents, index);
float x = transform.TranslateX - MathF.Abs(transform.ScaleX); float x = transform.TranslateX - MathF.Abs(transform.ScaleX);
float y = transform.TranslateY - MathF.Abs(transform.ScaleY); float y = transform.TranslateY - MathF.Abs(transform.ScaleY);
@ -303,7 +371,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
private void UpdateDepthBiasState() private void UpdateDepthBiasState()
{ {
var polygonOffset = _context.State.Get<DepthBiasState>(MethodOffset.DepthBiasState); var depthBias = _context.State.Get<DepthBiasState>(MethodOffset.DepthBiasState);
float factor = _context.State.Get<float>(MethodOffset.DepthBiasFactor); float factor = _context.State.Get<float>(MethodOffset.DepthBiasFactor);
float units = _context.State.Get<float>(MethodOffset.DepthBiasUnits); float units = _context.State.Get<float>(MethodOffset.DepthBiasUnits);
@ -311,18 +379,18 @@ namespace Ryujinx.Graphics.Gpu.Engine
PolygonModeMask enables = 0; PolygonModeMask enables = 0;
enables = (polygonOffset.PointEnable.IsTrue() ? PolygonModeMask.Point : 0); enables = (depthBias.PointEnable ? PolygonModeMask.Point : 0);
enables |= (polygonOffset.LineEnable.IsTrue() ? PolygonModeMask.Line : 0); enables |= (depthBias.LineEnable ? PolygonModeMask.Line : 0);
enables |= (polygonOffset.FillEnable.IsTrue() ? PolygonModeMask.Fill : 0); enables |= (depthBias.FillEnable ? PolygonModeMask.Fill : 0);
_context.Renderer.Pipeline.SetDepthBias(enables, factor, units, clamp); _context.Renderer.Pipeline.SetDepthBias(enables, factor, units, clamp);
} }
private void UpdateStencilTestState() private void UpdateStencilTestState()
{ {
StencilBackMasks backMasks = _context.State.GetStencilBackMasks(); var backMasks = _context.State.Get<StencilBackMasks> (MethodOffset.StencilBackMasks);
StencilTestState test = _context.State.GetStencilTestState(); var test = _context.State.Get<StencilTestState> (MethodOffset.StencilTestState);
StencilBackTestState backTest = _context.State.GetStencilBackTestState(); var backTest = _context.State.Get<StencilBackTestState>(MethodOffset.StencilBackTestState);
CompareOp backFunc; CompareOp backFunc;
StencilOp backSFail; StencilOp backSFail;
@ -332,7 +400,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
int backFuncMask; int backFuncMask;
int backMask; int backMask;
if (backTest.TwoSided.IsTrue()) if (backTest.TwoSided)
{ {
backFunc = backTest.BackFunc; backFunc = backTest.BackFunc;
backSFail = backTest.BackSFail; backSFail = backTest.BackSFail;
@ -354,7 +422,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
} }
_context.Renderer.Pipeline.SetStencilTest(new StencilTestDescriptor( _context.Renderer.Pipeline.SetStencilTest(new StencilTestDescriptor(
test.Enable.IsTrue(), test.Enable,
test.FrontFunc, test.FrontFunc,
test.FrontSFail, test.FrontSFail,
test.FrontDpPass, test.FrontDpPass,
@ -373,42 +441,18 @@ namespace Ryujinx.Graphics.Gpu.Engine
private void UpdateSamplerPoolState() private void UpdateSamplerPoolState()
{ {
PoolState samplerPool = _context.State.GetSamplerPoolState(); var samplerPool = _context.State.Get<PoolState>(MethodOffset.SamplerPoolState);
_textureManager.SetGraphicsSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId); _textureManager.SetGraphicsSamplerPool(samplerPool.Address.Pack(), samplerPool.MaximumId);
} }
private void UpdateTexturePoolState() private void UpdateTexturePoolState()
{ {
PoolState texturePool = _context.State.GetTexturePoolState(); var texturePool = _context.State.Get<PoolState>(MethodOffset.TexturePoolState);
_textureManager.SetGraphicsTexturePool(texturePool.Address.Pack(), texturePool.MaximumId); _textureManager.SetGraphicsTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);
_textureManager.SetGraphicsTextureBufferIndex(_context.State.GetTextureBufferIndex()); _textureManager.SetGraphicsTextureBufferIndex(_context.State.Get<int>(MethodOffset.TextureBufferIndex));
}
private void UpdateInputAssemblerGroupState()
{
// Must be updated before the vertex buffer.
if ((_context.State.StateWriteFlags & StateWriteFlags.VertexAttribState) != 0)
{
UpdateVertexAttribState();
}
if ((_context.State.StateWriteFlags & StateWriteFlags.PrimitiveRestartState) != 0)
{
UpdatePrimitiveRestartState();
}
if ((_context.State.StateWriteFlags & StateWriteFlags.IndexBufferState) != 0)
{
UpdateIndexBufferState();
}
if ((_context.State.StateWriteFlags & StateWriteFlags.VertexBufferState) != 0)
{
UpdateVertexBufferState();
}
} }
private void UpdateVertexAttribState() private void UpdateVertexAttribState()
@ -417,7 +461,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
for (int index = 0; index < 16; index++) for (int index = 0; index < 16; index++)
{ {
VertexAttribState vertexAttrib = _context.State.GetVertexAttribState(index); var vertexAttrib = _context.State.Get<VertexAttribState>(MethodOffset.VertexAttribState, index);
if (!FormatTable.TryGetAttribFormat(vertexAttrib.UnpackFormat(), out Format format)) if (!FormatTable.TryGetAttribFormat(vertexAttrib.UnpackFormat(), out Format format))
{ {
@ -446,7 +490,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
private void UpdateIndexBufferState() private void UpdateIndexBufferState()
{ {
IndexBufferState indexBuffer = _context.State.GetIndexBufferState(); var indexBuffer = _context.State.Get<IndexBufferState>(MethodOffset.IndexBufferState);
_firstIndex = indexBuffer.First; _firstIndex = indexBuffer.First;
_indexCount = indexBuffer.Count; _indexCount = indexBuffer.Count;
@ -475,70 +519,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
UpdateVertexBufferState(); UpdateVertexBufferState();
} }
private uint GetIndexBufferMaxIndex(ulong gpuVa, ulong size, IndexType type)
{
ulong address = _context.MemoryManager.Translate(gpuVa);
Span<byte> data = _context.PhysicalMemory.Read(address, size);
uint maxIndex = 0;
switch (type)
{
case IndexType.UByte:
{
for (int index = 0; index < data.Length; index++)
{
if (maxIndex < data[index])
{
maxIndex = data[index];
}
}
break;
}
case IndexType.UShort:
{
Span<ushort> indices = MemoryMarshal.Cast<byte, ushort>(data);
for (int index = 0; index < indices.Length; index++)
{
if (maxIndex < indices[index])
{
maxIndex = indices[index];
}
}
break;
}
case IndexType.UInt:
{
Span<uint> indices = MemoryMarshal.Cast<byte, uint>(data);
for (int index = 0; index < indices.Length; index++)
{
if (maxIndex < indices[index])
{
maxIndex = indices[index];
}
}
break;
}
}
return maxIndex;
}
private void UpdateVertexBufferState() private void UpdateVertexBufferState()
{ {
_isAnyVbInstanced = false; _isAnyVbInstanced = false;
for (int index = 0; index < 16; index++) for (int index = 0; index < 16; index++)
{ {
VertexBufferState vertexBuffer = _context.State.GetVertexBufferState(index); var vertexBuffer = _context.State.Get<VertexBufferState>(MethodOffset.VertexBufferState, index);
if (!vertexBuffer.UnpackEnable()) if (!vertexBuffer.UnpackEnable())
{ {
@ -547,13 +534,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
continue; continue;
} }
GpuVa endAddress = _context.State.GetVertexBufferEndAddress(index); GpuVa endAddress = _context.State.Get<GpuVa>(MethodOffset.VertexBufferEndAddress, index);
ulong address = vertexBuffer.Address.Pack(); ulong address = vertexBuffer.Address.Pack();
int stride = vertexBuffer.UnpackStride(); int stride = vertexBuffer.UnpackStride();
bool instanced = _context.State.Get<bool>(MethodOffset.VertexBufferInstanced + index); bool instanced = _context.State.Get<Boolean32>(MethodOffset.VertexBufferInstanced + index);
int divisor = instanced ? vertexBuffer.Divisor : 0; int divisor = instanced ? vertexBuffer.Divisor : 0;
@ -571,9 +558,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
// For non-indexed draws, we can guess the size from the vertex count // For non-indexed draws, we can guess the size from the vertex count
// and stride. // and stride.
int firstInstance = _context.State.GetBaseInstance(); int firstInstance = _context.State.Get<int>(MethodOffset.FirstInstance);
VertexBufferDrawState drawState = _context.State.GetVertexBufferDrawState(); var drawState = _context.State.Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
size = (ulong)((firstInstance + drawState.First + drawState.Count) * stride); size = (ulong)((firstInstance + drawState.First + drawState.Count) * stride);
} }
@ -584,9 +571,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
private void UpdateFaceState() private void UpdateFaceState()
{ {
FaceState face = _context.State.GetFaceState(); var face = _context.State.Get<FaceState>(MethodOffset.FaceState);
_context.Renderer.Pipeline.SetFaceCulling(face.CullEnable.IsTrue(), face.CullFace); _context.Renderer.Pipeline.SetFaceCulling(face.CullEnable, face.CullFace);
_context.Renderer.Pipeline.SetFrontFace(face.FrontFace); _context.Renderer.Pipeline.SetFrontFace(face.FrontFace);
} }
@ -597,7 +584,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
for (int index = 0; index < Constants.TotalRenderTargets; index++) for (int index = 0; index < Constants.TotalRenderTargets; index++)
{ {
RtColorMask colorMask = _context.State.Get<RtColorMask>(MethodOffset.RtColorMask + index); var colorMask = _context.State.Get<RtColorMask>(MethodOffset.RtColorMask, index);
uint componentMask = 0; uint componentMask = 0;
@ -618,12 +605,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
for (int index = 0; index < 8; index++) for (int index = 0; index < 8; index++)
{ {
bool blendEnable = _context.State.GetBlendEnable(index).IsTrue(); bool enable = _context.State.Get<Boolean32>(MethodOffset.BlendEnable, index);
BlendState blend = _context.State.GetBlendState(index); var blend = _context.State.Get<BlendState>(MethodOffset.BlendState, index);
BlendDescriptor descriptor = new BlendDescriptor( BlendDescriptor descriptor = new BlendDescriptor(
blendEnable, enable,
blend.ColorOp, blend.ColorOp,
blend.ColorSrcFactor, blend.ColorSrcFactor,
blend.ColorDstFactor, blend.ColorDstFactor,
@ -656,11 +643,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
Span<ulong> addressesArray = MemoryMarshal.Cast<ShaderAddresses, ulong>(addressesSpan); Span<ulong> addressesArray = MemoryMarshal.Cast<ShaderAddresses, ulong>(addressesSpan);
ulong baseAddress = _context.State.GetShaderBaseAddress().Pack(); ulong baseAddress = _context.State.Get<GpuVa>(MethodOffset.ShaderBaseAddress).Pack();
for (int index = 0; index < 6; index++) for (int index = 0; index < 6; index++)
{ {
ShaderState shader = _context.State.GetShaderState(index); var shader = _context.State.Get<ShaderState>(MethodOffset.ShaderState, index);
if (!shader.UnpackEnable() && index != 1) if (!shader.UnpackEnable() && index != 1)
{ {
@ -678,6 +665,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
ShaderProgramInfo info = gs.Shader[stage]?.Info; ShaderProgramInfo info = gs.Shader[stage]?.Info;
_currentProgramInfo[stage] = info;
if (info == null) if (info == null)
{ {
continue; continue;
@ -714,21 +703,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
for (int index = 0; index < info.SBuffers.Count; index++) for (int index = 0; index < info.SBuffers.Count; index++)
{ {
BufferDescriptor sb = info.SBuffers[index]; sbEnableMask |= 1u << info.SBuffers[index].Slot;
sbEnableMask |= 1u << sb.Slot;
ulong sbDescAddress = _bufferManager.GetGraphicsUniformBufferAddress(stage, 0);
int sbDescOffset = 0x110 + stage * 0x100 + sb.Slot * 0x10;
sbDescAddress += (ulong)sbDescOffset;
Span<byte> sbDescriptorData = _context.PhysicalMemory.Read(sbDescAddress, 0x10);
SbDescriptor sbDescriptor = MemoryMarshal.Cast<byte, SbDescriptor>(sbDescriptorData)[0];
_bufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size);
} }
for (int index = 0; index < info.CBuffers.Count; index++) for (int index = 0; index < info.CBuffers.Count; index++)

View file

@ -1,3 +1,4 @@
using Ryujinx.Graphics.Gpu.Memory;
using System; using System;
namespace Ryujinx.Graphics.Gpu.Image namespace Ryujinx.Graphics.Gpu.Image
@ -31,7 +32,7 @@ namespace Ryujinx.Graphics.Gpu.Image
public void SynchronizeMemory() public void SynchronizeMemory()
{ {
(ulong, ulong)[] modifiedRanges = Context.PhysicalMemory.GetModifiedRanges(Address, Size); (ulong, ulong)[] modifiedRanges = Context.PhysicalMemory.GetModifiedRanges(Address, Size, ResourceName.TexturePool);
for (int index = 0; index < modifiedRanges.Length; index++) for (int index = 0; index < modifiedRanges.Length; index++)
{ {

View file

@ -202,7 +202,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_sequenceNumber = _context.SequenceNumber; _sequenceNumber = _context.SequenceNumber;
bool modified = _context.PhysicalMemory.GetModifiedRanges(Address, Size).Length != 0; bool modified = _context.PhysicalMemory.GetModifiedRanges(Address, Size, ResourceName.Texture).Length != 0;
if (!modified && _hasData) if (!modified && _hasData)
{ {

View file

@ -114,7 +114,7 @@ namespace Ryujinx.Graphics.Gpu.Image
public void CommitComputeBindings() public void CommitComputeBindings()
{ {
// Evert time we switch between graphics and compute work, // Every time we switch between graphics and compute work,
// we must rebind everything. // we must rebind everything.
// Since compute work happens less often, we always do that // Since compute work happens less often, we always do that
// before and after the compute dispatch. // before and after the compute dispatch.

View file

@ -69,7 +69,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
return; return;
} }
(ulong, ulong)[] modifiedRanges = _context.PhysicalMemory.GetModifiedRanges(address, size); (ulong, ulong)[] modifiedRanges = _context.PhysicalMemory.GetModifiedRanges(address, size, ResourceName.Buffer);
for (int index = 0; index < modifiedRanges.Length; index++) for (int index = 0; index < modifiedRanges.Length; index++)
{ {

View file

@ -116,11 +116,15 @@ namespace Ryujinx.Graphics.Gpu.Memory
ulong address = TranslateAndCreateBuffer(gpuVa, size); ulong address = TranslateAndCreateBuffer(gpuVa, size);
_gpStorageBuffers[stage].Bind(index, address, size); if (_gpStorageBuffers[stage].Buffers[index].Address != address ||
_gpStorageBuffers[stage].Buffers[index].Size != size)
{
_gpStorageBuffersDirty = true; _gpStorageBuffersDirty = true;
} }
_gpStorageBuffers[stage].Bind(index, address, size);
}
public void SetComputeUniformBuffer(int index, ulong gpuVa, ulong size) public void SetComputeUniformBuffer(int index, ulong gpuVa, ulong size)
{ {
ulong address = TranslateAndCreateBuffer(gpuVa, size); ulong address = TranslateAndCreateBuffer(gpuVa, size);

View file

@ -10,6 +10,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
void Write(ulong address, Span<byte> data); void Write(ulong address, Span<byte> data);
(ulong, ulong)[] GetModifiedRanges(ulong address, ulong size); (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size, ResourceName name);
} }
} }

View file

@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
private const int PtLvl0Bits = 14; private const int PtLvl0Bits = 14;
private const int PtLvl1Bits = 14; private const int PtLvl1Bits = 14;
private const int PtPageBits = 12; public const int PtPageBits = 12;
private const ulong PtLvl0Size = 1UL << PtLvl0Bits; private const ulong PtLvl0Size = 1UL << PtLvl0Bits;
private const ulong PtLvl1Size = 1UL << PtLvl1Bits; private const ulong PtLvl1Size = 1UL << PtLvl1Bits;

View file

@ -0,0 +1,10 @@
namespace Ryujinx.Graphics.Gpu.Memory
{
public enum ResourceName
{
Buffer,
Texture,
TexturePool,
SamplerPool
}
}

View file

@ -4,12 +4,13 @@ namespace Ryujinx.Graphics.Gpu.State
{ {
struct BlendState struct BlendState
{ {
public Bool SeparateAlpha; public Boolean32 SeparateAlpha;
public BlendOp ColorOp; public BlendOp ColorOp;
public BlendFactor ColorSrcFactor; public BlendFactor ColorSrcFactor;
public BlendFactor ColorDstFactor; public BlendFactor ColorDstFactor;
public BlendOp AlphaOp; public BlendOp AlphaOp;
public BlendFactor AlphaSrcFactor; public BlendFactor AlphaSrcFactor;
public BlendFactor AlphaDstFactor; public BlendFactor AlphaDstFactor;
public uint Padding;
} }
} }

View file

@ -1,17 +0,0 @@
namespace Ryujinx.Graphics.Gpu.State
{
struct Bool
{
private uint _value;
public bool IsTrue()
{
return (_value & 1) != 0;
}
public bool IsFalse()
{
return (_value & 1) == 0;
}
}
}

View file

@ -0,0 +1,12 @@
namespace Ryujinx.Graphics.Gpu.State
{
struct Boolean32
{
private uint _value;
public static implicit operator bool(Boolean32 value)
{
return (value._value & 1) != 0;
}
}
}

View file

@ -3,7 +3,7 @@ namespace Ryujinx.Graphics.Gpu.State
struct CopyTexture struct CopyTexture
{ {
public RtFormat Format; public RtFormat Format;
public bool LinearLayout; public Boolean32 LinearLayout;
public MemoryLayout MemoryLayout; public MemoryLayout MemoryLayout;
public int Depth; public int Depth;
public int Layer; public int Layer;

View file

@ -2,8 +2,8 @@ namespace Ryujinx.Graphics.Gpu.State
{ {
struct DepthBiasState struct DepthBiasState
{ {
public Bool PointEnable; public Boolean32 PointEnable;
public Bool LineEnable; public Boolean32 LineEnable;
public Bool FillEnable; public Boolean32 FillEnable;
} }
} }

View file

@ -4,7 +4,7 @@ namespace Ryujinx.Graphics.Gpu.State
{ {
struct FaceState struct FaceState
{ {
public Bool CullEnable; public Boolean32 CullEnable;
public FrontFace FrontFace; public FrontFace FrontFace;
public Face CullFace; public Face CullFace;
} }

View file

@ -1,6 +1,4 @@
using Ryujinx.Graphics.GAL; using System;
using Ryujinx.Graphics.Gpu.Image;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.State namespace Ryujinx.Graphics.Gpu.State
@ -17,39 +15,54 @@ namespace Ryujinx.Graphics.Gpu.State
{ {
public MethodCallback Callback; public MethodCallback Callback;
public StateWriteFlags WriteFlag; public MethodOffset BaseOffset;
public int Stride;
public int Count;
public bool Modified;
} }
private Register[] _registers; private Register[] _registers;
public StateWriteFlags StateWriteFlags { get; set; }
public GpuState() public GpuState()
{ {
_backingMemory = new int[RegistersCount]; _backingMemory = new int[RegistersCount];
_registers = new Register[RegistersCount]; _registers = new Register[RegistersCount];
StateWriteFlags = StateWriteFlags.Any; for (int index = 0; index < _registers.Length; index++)
{
InitializeDefaultState(); _registers[index].BaseOffset = (MethodOffset)index;
InitializeStateWatchers(); _registers[index].Stride = 1;
_registers[index].Count = 1;
_registers[index].Modified = true;
} }
public bool ExitEarly; foreach (var item in GpuStateTable.Table)
{
int totalRegs = item.Size * item.Count;
for (int regOffset = 0; regOffset < totalRegs; regOffset++)
{
int index = (int)item.Offset + regOffset;
_registers[index].BaseOffset = item.Offset;
_registers[index].Stride = item.Size;
_registers[index].Count = item.Count;
}
}
InitializeDefaultState();
}
public void CallMethod(MethodParams meth) public void CallMethod(MethodParams meth)
{ {
if (ExitEarly)
{
return;
}
Register register = _registers[meth.Method]; Register register = _registers[meth.Method];
if (_backingMemory[meth.Method] != meth.Argument) if (_backingMemory[meth.Method] != meth.Argument)
{ {
StateWriteFlags |= register.WriteFlag; _registers[(int)register.BaseOffset].Modified = true;
} }
_backingMemory[meth.Method] = meth.Argument; _backingMemory[meth.Method] = meth.Argument;
@ -67,264 +80,11 @@ namespace Ryujinx.Graphics.Gpu.State
return _backingMemory[offset]; return _backingMemory[offset];
} }
public void RegisterCopyBufferCallback(MethodCallback callback)
{
RegisterCallback(0xc0, callback);
}
public void RegisterCopyTextureCallback(MethodCallback callback)
{
RegisterCallback(0x237, callback);
}
public void RegisterDrawEndCallback(MethodCallback callback)
{
RegisterCallback(0x585, callback);
}
public void RegisterDrawBeginCallback(MethodCallback callback)
{
RegisterCallback(0x586, callback);
}
public void RegisterSetIndexCountCallback(MethodCallback callback)
{
RegisterCallback(0x5f8, callback);
}
public void RegisterClearCallback(MethodCallback callback)
{
RegisterCallback(0x674, callback);
}
public void RegisterReportCallback(MethodCallback callback)
{
RegisterCallback(0x6c3, callback);
}
public void RegisterUniformBufferUpdateCallback(MethodCallback callback)
{
for (int index = 0; index < 16; index++)
{
RegisterCallback(0x8e4 + index, callback);
}
}
public void RegisterUniformBufferBind0Callback(MethodCallback callback)
{
RegisterCallback(0x904, callback);
}
public void RegisterUniformBufferBind1Callback(MethodCallback callback)
{
RegisterCallback(0x90c, callback);
}
public void RegisterUniformBufferBind2Callback(MethodCallback callback)
{
RegisterCallback(0x914, callback);
}
public void RegisterUniformBufferBind3Callback(MethodCallback callback)
{
RegisterCallback(0x91c, callback);
}
public void RegisterUniformBufferBind4Callback(MethodCallback callback)
{
RegisterCallback(0x924, callback);
}
public CopyTexture GetCopyDstTexture()
{
return Get<CopyTexture>(MethodOffset.CopyDstTexture);
}
public CopyTexture GetCopySrcTexture()
{
return Get<CopyTexture>(MethodOffset.CopySrcTexture);
}
public RtColorState GetRtColorState(int index)
{
return Get<RtColorState>(MethodOffset.RtColorState + 16 * index);
}
public CopyTextureControl GetCopyTextureControl()
{
return Get<CopyTextureControl>(MethodOffset.CopyTextureControl);
}
public CopyRegion GetCopyRegion()
{
return Get<CopyRegion>(MethodOffset.CopyRegion);
}
public ViewportTransform GetViewportTransform(int index)
{
return Get<ViewportTransform>(MethodOffset.ViewportTransform + 8 * index);
}
public ViewportExtents GetViewportExtents(int index)
{
return Get<ViewportExtents>(MethodOffset.ViewportExtents + 4 * index);
}
public VertexBufferDrawState GetVertexBufferDrawState()
{
return Get<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState);
}
public ClearColors GetClearColors()
{
return Get<ClearColors>(MethodOffset.ClearColors);
}
public float GetClearDepthValue()
{
return Get<float>(MethodOffset.ClearDepthValue);
}
public int GetClearStencilValue()
{
return _backingMemory[(int)MethodOffset.ClearStencilValue];
}
public StencilBackMasks GetStencilBackMasks()
{
return Get<StencilBackMasks>(MethodOffset.StencilBackMasks);
}
public RtDepthStencilState GetRtDepthStencilState()
{
return Get<RtDepthStencilState>(MethodOffset.RtDepthStencilState);
}
public VertexAttribState GetVertexAttribState(int index)
{
return Get<VertexAttribState>(MethodOffset.VertexAttribState + index);
}
public Size3D GetRtDepthStencilSize()
{
return Get<Size3D>(MethodOffset.RtDepthStencilSize);
}
public Bool GetDepthTestEnable()
{
return Get<Bool>(MethodOffset.DepthTestEnable);
}
public CompareOp GetDepthTestFunc()
{
return Get<CompareOp>(MethodOffset.DepthTestFunc);
}
public Bool GetDepthWriteEnable()
{
return Get<Bool>(MethodOffset.DepthWriteEnable);
}
public Bool GetBlendEnable(int index)
{
return Get<Bool>(MethodOffset.BlendEnable + index);
}
public StencilTestState GetStencilTestState()
{
return Get<StencilTestState>(MethodOffset.StencilTestState);
}
public int GetBaseVertex()
{
return _backingMemory[(int)MethodOffset.FirstVertex];
}
public int GetBaseInstance()
{
return _backingMemory[(int)MethodOffset.FirstInstance];
}
public PoolState GetSamplerPoolState()
{
return Get<PoolState>(MethodOffset.SamplerPoolState);
}
public PoolState GetTexturePoolState()
{
return Get<PoolState>(MethodOffset.TexturePoolState);
}
public StencilBackTestState GetStencilBackTestState()
{
return Get<StencilBackTestState>(MethodOffset.StencilBackTestState);
}
public TextureMsaaMode GetRtMsaaMode()
{
return Get<TextureMsaaMode>(MethodOffset.RtMsaaMode);
}
public GpuVa GetShaderBaseAddress()
{
return Get<GpuVa>(MethodOffset.ShaderBaseAddress);
}
public PrimitiveRestartState GetPrimitiveRestartState()
{
return Get<PrimitiveRestartState>(MethodOffset.PrimitiveRestartState);
}
public IndexBufferState GetIndexBufferState()
{
return Get<IndexBufferState>(MethodOffset.IndexBufferState);
}
public FaceState GetFaceState()
{
return Get<FaceState>(MethodOffset.FaceState);
}
public ReportState GetReportState()
{
return Get<ReportState>(MethodOffset.ReportState);
}
public VertexBufferState GetVertexBufferState(int index)
{
return Get<VertexBufferState>(MethodOffset.VertexBufferState + 4 * index);
}
public BlendState GetBlendState(int index)
{
return Get<BlendState>(MethodOffset.BlendState + 8 * index);
}
public GpuVa GetVertexBufferEndAddress(int index)
{
return Get<GpuVa>(MethodOffset.VertexBufferEndAddress + 2 * index);
}
public ShaderState GetShaderState(int index)
{
return Get<ShaderState>(MethodOffset.ShaderState + 16 * index);
}
public UniformBufferState GetUniformBufferState()
{
return Get<UniformBufferState>(MethodOffset.UniformBufferState);
}
public void SetUniformBufferOffset(int offset) public void SetUniformBufferOffset(int offset)
{ {
_backingMemory[(int)MethodOffset.UniformBufferState + 3] = offset; _backingMemory[(int)MethodOffset.UniformBufferState + 3] = offset;
} }
public int GetTextureBufferIndex()
{
return _backingMemory[(int)MethodOffset.TextureBufferIndex];
}
private void InitializeDefaultState() private void InitializeDefaultState()
{ {
// Depth ranges. // Depth ranges.
@ -341,69 +101,11 @@ namespace Ryujinx.Graphics.Gpu.State
_backingMemory[(int)MethodOffset.RtColorMask] = 0x1111; _backingMemory[(int)MethodOffset.RtColorMask] = 0x1111;
} }
private void InitializeStateWatchers() public void RegisterCallback(MethodOffset offset, int count, MethodCallback callback)
{ {
SetWriteStateFlag(MethodOffset.RtColorState, StateWriteFlags.RtColorState, 16 * 8); for (int index = 0; index < count; index++)
SetWriteStateFlag(MethodOffset.ViewportTransform, StateWriteFlags.ViewportTransform, 8 * 8);
SetWriteStateFlag(MethodOffset.ViewportExtents, StateWriteFlags.ViewportTransform, 4 * 8);
SetWriteStateFlag<VertexBufferDrawState>(MethodOffset.VertexBufferDrawState, StateWriteFlags.VertexBufferState);
SetWriteStateFlag<DepthBiasState>(MethodOffset.DepthBiasState, StateWriteFlags.DepthBiasState);
SetWriteStateFlag(MethodOffset.DepthBiasFactor, StateWriteFlags.DepthBiasState, 1);
SetWriteStateFlag(MethodOffset.DepthBiasUnits, StateWriteFlags.DepthBiasState, 1);
SetWriteStateFlag(MethodOffset.DepthBiasClamp, StateWriteFlags.DepthBiasState, 1);
SetWriteStateFlag<RtDepthStencilState>(MethodOffset.RtDepthStencilState, StateWriteFlags.RtDepthStencilState);
SetWriteStateFlag<Size3D> (MethodOffset.RtDepthStencilSize, StateWriteFlags.RtDepthStencilState);
SetWriteStateFlag(MethodOffset.DepthTestEnable, StateWriteFlags.DepthTestState, 1);
SetWriteStateFlag(MethodOffset.DepthWriteEnable, StateWriteFlags.DepthTestState, 1);
SetWriteStateFlag(MethodOffset.DepthTestFunc, StateWriteFlags.DepthTestState, 1);
SetWriteStateFlag(MethodOffset.VertexAttribState, StateWriteFlags.VertexAttribState, 16);
SetWriteStateFlag<StencilBackMasks> (MethodOffset.StencilBackMasks, StateWriteFlags.StencilTestState);
SetWriteStateFlag<StencilTestState> (MethodOffset.StencilTestState, StateWriteFlags.StencilTestState);
SetWriteStateFlag<StencilBackTestState>(MethodOffset.StencilBackTestState, StateWriteFlags.StencilTestState);
SetWriteStateFlag<PoolState>(MethodOffset.SamplerPoolState, StateWriteFlags.SamplerPoolState);
SetWriteStateFlag<PoolState>(MethodOffset.TexturePoolState, StateWriteFlags.TexturePoolState);
SetWriteStateFlag<ShaderState>(MethodOffset.ShaderBaseAddress, StateWriteFlags.ShaderState);
SetWriteStateFlag<PrimitiveRestartState>(MethodOffset.PrimitiveRestartState, StateWriteFlags.PrimitiveRestartState);
SetWriteStateFlag<IndexBufferState>(MethodOffset.IndexBufferState, StateWriteFlags.IndexBufferState);
SetWriteStateFlag<FaceState>(MethodOffset.FaceState, StateWriteFlags.FaceState);
SetWriteStateFlag<RtColorMask>(MethodOffset.RtColorMask, StateWriteFlags.RtColorMask);
SetWriteStateFlag(MethodOffset.VertexBufferInstanced, StateWriteFlags.VertexBufferState, 16);
SetWriteStateFlag(MethodOffset.VertexBufferState, StateWriteFlags.VertexBufferState, 4 * 16);
SetWriteStateFlag(MethodOffset.VertexBufferEndAddress, StateWriteFlags.VertexBufferState, 2 * 16);
SetWriteStateFlag(MethodOffset.BlendEnable, StateWriteFlags.BlendState, 8);
SetWriteStateFlag(MethodOffset.BlendState, StateWriteFlags.BlendState, 8 * 8);
SetWriteStateFlag(MethodOffset.ShaderState, StateWriteFlags.ShaderState, 16 * 6);
SetWriteStateFlag(MethodOffset.TextureBufferIndex, StateWriteFlags.TexturePoolState, 1);
}
private void SetWriteStateFlag<T>(MethodOffset offset, StateWriteFlags flag)
{ {
SetWriteStateFlag(offset, flag, Marshal.SizeOf<T>()); _registers[(int)offset + index].Callback = callback;
}
private void SetWriteStateFlag(MethodOffset offset, StateWriteFlags flag, int size)
{
for (int index = 0; index < size; index++)
{
_registers[(int)offset + index].WriteFlag = flag;
} }
} }
@ -412,9 +114,37 @@ namespace Ryujinx.Graphics.Gpu.State
_registers[(int)offset].Callback = callback; _registers[(int)offset].Callback = callback;
} }
private void RegisterCallback(int offset, MethodCallback callback) public bool QueryModified(params MethodOffset[] offsets)
{ {
_registers[offset].Callback = callback; bool modified = false;
for (int index = 0; index < offsets.Length; index++)
{
modified |= QueryModified(offsets[index]);
}
return modified;
}
public bool QueryModified(MethodOffset offset)
{
bool modified = _registers[(int)offset].Modified;
_registers[(int)offset].Modified = false;
return modified;
}
public T Get<T>(MethodOffset offset, int index) where T : struct
{
Register register = _registers[(int)offset];
if ((uint)index >= register.Count)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return Get<T>(offset + index * register.Stride);
} }
public T Get<T>(MethodOffset offset) where T : struct public T Get<T>(MethodOffset offset) where T : struct

View file

@ -0,0 +1,56 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.State
{
static class GpuStateTable
{
public struct TableItem
{
public MethodOffset Offset { get; }
public int Size { get; }
public int Count { get; }
public TableItem(MethodOffset offset, Type type, int count)
{
int sizeInBytes = Marshal.SizeOf(type);
Debug.Assert((sizeInBytes & 3) == 0);
Offset = offset;
Size = sizeInBytes / 4;
Count = count;
}
}
public static TableItem[] Table = new TableItem[]
{
new TableItem(MethodOffset.RtColorState, typeof(RtColorState), 8),
new TableItem(MethodOffset.ViewportTransform, typeof(ViewportTransform), 8),
new TableItem(MethodOffset.ViewportExtents, typeof(ViewportExtents), 8),
new TableItem(MethodOffset.VertexBufferDrawState, typeof(VertexBufferDrawState), 1),
new TableItem(MethodOffset.DepthBiasState, typeof(DepthBiasState), 1),
new TableItem(MethodOffset.StencilBackMasks, typeof(StencilBackMasks), 1),
new TableItem(MethodOffset.RtDepthStencilState, typeof(RtDepthStencilState), 1),
new TableItem(MethodOffset.VertexAttribState, typeof(VertexAttribState), 16),
new TableItem(MethodOffset.RtDepthStencilSize, typeof(Size3D), 1),
new TableItem(MethodOffset.BlendEnable, typeof(Boolean32), 8),
new TableItem(MethodOffset.StencilTestState, typeof(StencilTestState), 1),
new TableItem(MethodOffset.SamplerPoolState, typeof(PoolState), 1),
new TableItem(MethodOffset.TexturePoolState, typeof(PoolState), 1),
new TableItem(MethodOffset.StencilBackTestState, typeof(StencilBackTestState), 1),
new TableItem(MethodOffset.ShaderBaseAddress, typeof(GpuVa), 1),
new TableItem(MethodOffset.PrimitiveRestartState, typeof(PrimitiveRestartState), 1),
new TableItem(MethodOffset.IndexBufferState, typeof(IndexBufferState), 1),
new TableItem(MethodOffset.VertexBufferInstanced, typeof(Boolean32), 16),
new TableItem(MethodOffset.FaceState, typeof(FaceState), 1),
new TableItem(MethodOffset.RtColorMask, typeof(RtColorMask), 8),
new TableItem(MethodOffset.VertexBufferState, typeof(VertexBufferState), 16),
new TableItem(MethodOffset.BlendState, typeof(BlendState), 8),
new TableItem(MethodOffset.VertexBufferEndAddress, typeof(GpuVa), 16),
new TableItem(MethodOffset.ShaderState, typeof(ShaderState), 6),
};
}
}

View file

@ -9,10 +9,5 @@ namespace Ryujinx.Graphics.Gpu.State
{ {
return Low | ((ulong)High << 32); return Low | ((ulong)High << 32);
} }
public bool IsNullPtr()
{
return (Low | High) == 0;
}
} }
} }

View file

@ -2,13 +2,14 @@ namespace Ryujinx.Graphics.Gpu.State
{ {
enum MethodOffset enum MethodOffset
{ {
Inline2MemoryParams = 0x60, I2mParams = 0x60,
Inline2MemoryExecute = 0x6c, LaunchDma = 0x6c,
Inline2MemoryPushData = 0x6d, LoadInlineData = 0x6d,
CopyDstTexture = 0x80, CopyDstTexture = 0x80,
CopySrcTexture = 0x8c, CopySrcTexture = 0x8c,
DispatchParamsAddress = 0xad, DispatchParamsAddress = 0xad,
Dispatch = 0xaf, Dispatch = 0xaf,
CopyBuffer = 0xc0,
CopyBufferParams = 0x100, CopyBufferParams = 0x100,
CopyBufferSwizzle = 0x1c2, CopyBufferSwizzle = 0x1c2,
CopyBufferDstTexture = 0x1c3, CopyBufferDstTexture = 0x1c3,
@ -16,6 +17,7 @@ namespace Ryujinx.Graphics.Gpu.State
RtColorState = 0x200, RtColorState = 0x200,
CopyTextureControl = 0x223, CopyTextureControl = 0x223,
CopyRegion = 0x22c, CopyRegion = 0x22c,
CopyTexture = 0x237,
ViewportTransform = 0x280, ViewportTransform = 0x280,
ViewportExtents = 0x300, ViewportExtents = 0x300,
VertexBufferDrawState = 0x35d, VertexBufferDrawState = 0x35d,
@ -47,18 +49,29 @@ namespace Ryujinx.Graphics.Gpu.State
DepthBiasUnits = 0x56f, DepthBiasUnits = 0x56f,
RtMsaaMode = 0x574, RtMsaaMode = 0x574,
ShaderBaseAddress = 0x582, ShaderBaseAddress = 0x582,
DrawEnd = 0x585,
DrawBegin = 0x586,
PrimitiveRestartState = 0x591, PrimitiveRestartState = 0x591,
IndexBufferState = 0x5f2, IndexBufferState = 0x5f2,
IndexBufferCount = 0x5f8,
DepthBiasClamp = 0x61f, DepthBiasClamp = 0x61f,
VertexBufferInstanced = 0x620, VertexBufferInstanced = 0x620,
FaceState = 0x646, FaceState = 0x646,
Clear = 0x674,
RtColorMask = 0x680, RtColorMask = 0x680,
ReportState = 0x6c0, ReportState = 0x6c0,
Report = 0x6c3,
VertexBufferState = 0x700, VertexBufferState = 0x700,
BlendState = 0x780, BlendState = 0x780,
VertexBufferEndAddress = 0x7c0, VertexBufferEndAddress = 0x7c0,
ShaderState = 0x800, ShaderState = 0x800,
UniformBufferState = 0x8e0, UniformBufferState = 0x8e0,
UniformBufferUpdateData = 0x8e4,
UniformBufferBindVertex = 0x904,
UniformBufferBindTessControl = 0x90c,
UniformBufferBindTessEvaluation = 0x914,
UniformBufferBindGeometry = 0x91c,
UniformBufferBindFragment = 0x924,
TextureBufferIndex = 0x982 TextureBufferIndex = 0x982
} }
} }

View file

@ -2,7 +2,7 @@ namespace Ryujinx.Graphics.Gpu.State
{ {
struct PrimitiveRestartState struct PrimitiveRestartState
{ {
public bool Enable; public Boolean32 Enable;
public int Index; public int Index;
} }
} }

View file

@ -9,5 +9,13 @@ namespace Ryujinx.Graphics.Gpu.State
public MemoryLayout MemoryLayout; public MemoryLayout MemoryLayout;
public int Depth; public int Depth;
public int LayerSize; public int LayerSize;
public int BaseLayer;
public int Unknown0x24;
public int Padding0;
public int Padding1;
public int Padding2;
public int Padding3;
public int Padding4;
public int Padding5;
} }
} }

View file

@ -8,6 +8,8 @@ namespace Ryujinx.Graphics.Gpu.State
D32Float = 0xa, D32Float = 0xa,
D16Unorm = 0x13, D16Unorm = 0x13,
D24UnormS8Uint = 0x14, D24UnormS8Uint = 0x14,
D24Unorm = 0x15,
S8UintD24Unorm = 0x16,
S8Uint = 0x17, S8Uint = 0x17,
D32FloatS8Uint = 0x19, D32FloatS8Uint = 0x19,
R32G32B32A32Float = 0xc0, R32G32B32A32Float = 0xc0,
@ -74,6 +76,8 @@ namespace Ryujinx.Graphics.Gpu.State
case RtFormat.D32Float: return new FormatInfo(Format.D32Float, 1, 1, 4); case RtFormat.D32Float: return new FormatInfo(Format.D32Float, 1, 1, 4);
case RtFormat.D16Unorm: return new FormatInfo(Format.D16Unorm, 1, 1, 2); case RtFormat.D16Unorm: return new FormatInfo(Format.D16Unorm, 1, 1, 2);
case RtFormat.D24UnormS8Uint: return new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4); case RtFormat.D24UnormS8Uint: return new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4);
case RtFormat.D24Unorm: return new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4);
case RtFormat.S8UintD24Unorm: return new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4);
case RtFormat.S8Uint: return new FormatInfo(Format.S8Uint, 1, 1, 1); case RtFormat.S8Uint: return new FormatInfo(Format.S8Uint, 1, 1, 1);
case RtFormat.D32FloatS8Uint: return new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8); case RtFormat.D32FloatS8Uint: return new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8);
case RtFormat.R32G32B32A32Float: return new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16); case RtFormat.R32G32B32A32Float: return new FormatInfo(Format.R32G32B32A32Float, 1, 1, 16);

View file

@ -10,6 +10,14 @@ namespace Ryujinx.Graphics.Gpu.State
public uint Unknown0x14; public uint Unknown0x14;
public uint Unknown0x18; public uint Unknown0x18;
public uint Unknown0x1c; public uint Unknown0x1c;
public uint Unknown0x20;
public uint Unknown0x24;
public uint Unknown0x28;
public uint Unknown0x2c;
public uint Unknown0x30;
public uint Unknown0x34;
public uint Unknown0x38;
public uint Unknown0x3c;
public bool UnpackEnable() public bool UnpackEnable()
{ {

View file

@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Gpu.State
{ {
struct StencilBackTestState struct StencilBackTestState
{ {
public Bool TwoSided; public Boolean32 TwoSided;
public StencilOp BackSFail; public StencilOp BackSFail;
public StencilOp BackDpFail; public StencilOp BackDpFail;
public StencilOp BackDpPass; public StencilOp BackDpPass;

View file

@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Gpu.State
{ {
struct StencilTestState struct StencilTestState
{ {
public Bool Enable; public Boolean32 Enable;
public StencilOp FrontSFail; public StencilOp FrontSFail;
public StencilOp FrontDpFail; public StencilOp FrontDpFail;
public StencilOp FrontDpPass; public StencilOp FrontDpPass;

View file

@ -905,6 +905,8 @@ namespace Ryujinx.Graphics.OpenGL
} }
private void RestoreComponentMask(int index) private void RestoreComponentMask(int index)
{
if (_componentMasks != null)
{ {
GL.ColorMask( GL.ColorMask(
index, index,
@ -913,6 +915,7 @@ namespace Ryujinx.Graphics.OpenGL
(_componentMasks[index] & 4u) != 0, (_componentMasks[index] & 4u) != 0,
(_componentMasks[index] & 8u) != 0); (_componentMasks[index] & 8u) != 0);
} }
}
public void RebindProgram() public void RebindProgram()
{ {

View file

@ -6,6 +6,5 @@ namespace Ryujinx.Graphics.Shader.Decoders
Green = 1 << 1, Green = 1 << 1,
Blue = 1 << 2, Blue = 1 << 2,
Alpha = 1 << 3 Alpha = 1 << 3
} }
} }

View file

@ -2,6 +2,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
{ {
enum SystemRegister enum SystemRegister
{ {
ThreadId = 0x20,
ThreadIdX = 0x21, ThreadIdX = 0x21,
ThreadIdY = 0x22, ThreadIdY = 0x22,
ThreadIdZ = 0x23, ThreadIdZ = 0x23,

View file

@ -27,6 +27,20 @@ namespace Ryujinx.Graphics.Shader.Instructions
switch (sysReg) switch (sysReg)
{ {
case SystemRegister.ThreadId:
{
Operand tidX = Attribute(AttributeConsts.ThreadIdX);
Operand tidY = Attribute(AttributeConsts.ThreadIdY);
Operand tidZ = Attribute(AttributeConsts.ThreadIdZ);
tidY = context.ShiftLeft(tidY, Const(16));
tidZ = context.ShiftLeft(tidZ, Const(26));
src = context.BitwiseOr(tidX, context.BitwiseOr(tidY, tidZ));
break;
}
case SystemRegister.ThreadIdX: src = Attribute(AttributeConsts.ThreadIdX); break; case SystemRegister.ThreadIdX: src = Attribute(AttributeConsts.ThreadIdX); break;
case SystemRegister.ThreadIdY: src = Attribute(AttributeConsts.ThreadIdY); break; case SystemRegister.ThreadIdY: src = Attribute(AttributeConsts.ThreadIdY); break;
case SystemRegister.ThreadIdZ: src = Attribute(AttributeConsts.ThreadIdZ); break; case SystemRegister.ThreadIdZ: src = Attribute(AttributeConsts.ThreadIdZ); break;

View file

@ -59,6 +59,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
Add(Instruction.ExponentB2, VariableType.Scalar, VariableType.Scalar); Add(Instruction.ExponentB2, VariableType.Scalar, VariableType.Scalar);
Add(Instruction.Floor, VariableType.F32, VariableType.F32); Add(Instruction.Floor, VariableType.F32, VariableType.F32);
Add(Instruction.FusedMultiplyAdd, VariableType.F32, VariableType.F32, VariableType.F32, VariableType.F32); Add(Instruction.FusedMultiplyAdd, VariableType.F32, VariableType.F32, VariableType.F32, VariableType.F32);
Add(Instruction.ImageLoad, VariableType.F32);
Add(Instruction.ImageStore, VariableType.None);
Add(Instruction.IsNan, VariableType.Bool, VariableType.F32); Add(Instruction.IsNan, VariableType.Bool, VariableType.F32);
Add(Instruction.LoadAttribute, VariableType.F32, VariableType.S32, VariableType.S32); Add(Instruction.LoadAttribute, VariableType.F32, VariableType.S32, VariableType.S32);
Add(Instruction.LoadConstant, VariableType.F32, VariableType.S32, VariableType.S32); Add(Instruction.LoadConstant, VariableType.F32, VariableType.S32, VariableType.S32);
@ -105,7 +107,11 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
public static VariableType GetSrcVarType(Instruction inst, int index) public static VariableType GetSrcVarType(Instruction inst, int index)
{ {
if (inst == Instruction.TextureSample) // TODO: Return correct type depending on source index,
// that can improve the decompiler output.
if (inst == Instruction.TextureSample ||
inst == Instruction.ImageLoad ||
inst == Instruction.ImageStore)
{ {
return VariableType.F32; return VariableType.F32;
} }

View file

@ -59,9 +59,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types
_cpuMemory.WriteBytes((long)address, data.ToArray()); _cpuMemory.WriteBytes((long)address, data.ToArray());
} }
public (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size) public (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size, ResourceName name)
{ {
return _cpuMemory.GetModifiedRanges(address, size); return _cpuMemory.GetModifiedRanges(address, size, (int)name);
} }
public int GetPageSize() public int GetPageSize()