/// <summary> /// Performs an incrementation on a syncpoint. /// </summary> /// <param name="argument">Method call argument</param> public void IncrementSyncpoint(int argument) { uint syncpointId = (uint)argument & 0xFFFF; _context.AdvanceSequence(); _context.CreateHostSyncIfNeeded(true); _context.Renderer.UpdateCounters(); // Poll the query counters, the game may want an updated result. _context.Synchronization.IncrementSyncpoint(syncpointId); }
/// <summary> /// Performs actual copy of the inline data after the transfer is finished. /// </summary> private void FinishTransfer() { Span <byte> data = MemoryMarshal.Cast <int, byte>(_buffer).Slice(0, _size); if (_isLinear && _lineCount == 1) { ulong address = _channel.MemoryManager.Translate(_dstGpuVa); _channel.MemoryManager.Physical.Write(address, data); } else { var dstCalculator = new OffsetCalculator( _dstWidth, _dstHeight, _dstStride, _isLinear, _dstGobBlocksInY, 1); int srcOffset = 0; ulong dstBaseAddress = _channel.MemoryManager.Translate(_dstGpuVa); for (int y = _dstY; y < _dstY + _lineCount; y++) { int x1 = _dstX; int x2 = _dstX + _lineLengthIn; int x2Trunc = _dstX + BitUtils.AlignDown(_lineLengthIn, 16); int x; for (x = x1; x < x2Trunc; x += 16, srcOffset += 16) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = dstBaseAddress + (ulong)dstOffset; Span <byte> pixel = data.Slice(srcOffset, 16); _channel.MemoryManager.Physical.Write(dstAddress, pixel); } for (; x < x2; x++, srcOffset++) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = dstBaseAddress + (ulong)dstOffset; Span <byte> pixel = data.Slice(srcOffset, 1); _channel.MemoryManager.Physical.Write(dstAddress, pixel); } } } _finished = true; _context.AdvanceSequence(); }
/// <summary> /// Apply a fence operation on a syncpoint. /// </summary> /// <param name="argument">Method call argument</param> public void Syncpointb(int argument) { SyncpointbOperation operation = _state.State.SyncpointbOperation; uint syncpointId = (uint)_state.State.SyncpointbSyncptIndex; if (operation == SyncpointbOperation.Wait) { uint threshold = (uint)_state.State.SyncpointaPayload; _context.Synchronization.WaitOnSyncpoint(syncpointId, threshold, Timeout.InfiniteTimeSpan); } else if (operation == SyncpointbOperation.Incr) { _context.Synchronization.IncrementSyncpoint(syncpointId); } _context.AdvanceSequence(); }
/// <summary> /// Writes (or Releases) a GPU semaphore value to guest memory. /// </summary> private void ReleaseSemaphore() { _channel.MemoryManager.Write(_state.State.SemaphoreAddress.Pack(), _state.State.SemaphorePayload); _context.AdvanceSequence(); }
/// <summary> /// Performs actual copy of the inline data after the transfer is finished. /// </summary> private void FinishTransfer() { var memoryManager = _channel.MemoryManager; var data = MemoryMarshal.Cast <int, byte>(_buffer).Slice(0, _size); if (_isLinear && _lineCount == 1) { memoryManager.WriteTrackedResource(_dstGpuVa, data.Slice(0, _lineLengthIn)); _context.AdvanceSequence(); } else { // TODO: Verify if the destination X/Y and width/height are taken into account // for linear texture transfers. If not, we can use the fast path for that aswell. // Right now the copy code at the bottom assumes that it is used on both which might be incorrect. if (!_isLinear) { var target = memoryManager.Physical.TextureCache.FindTexture( memoryManager, _dstGpuVa, 1, _dstStride, _dstHeight, _lineLengthIn, _lineCount, _isLinear, _dstGobBlocksInY, _dstGobBlocksInZ); if (target != null) { target.SetData(data, 0, 0, new GAL.Rectangle <int>(_dstX, _dstY, _lineLengthIn / target.Info.FormatInfo.BytesPerPixel, _lineCount)); return; } } var dstCalculator = new OffsetCalculator( _dstWidth, _dstHeight, _dstStride, _isLinear, _dstGobBlocksInY, 1); int srcOffset = 0; for (int y = _dstY; y < _dstY + _lineCount; y++) { int x1 = _dstX; int x2 = _dstX + _lineLengthIn; int x1Round = BitUtils.AlignUp(_dstX, 16); int x2Trunc = BitUtils.AlignDown(x2, 16); int x = x1; if (x1Round <= x2) { for (; x < x1Round; x++, srcOffset++) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = _dstGpuVa + (uint)dstOffset; memoryManager.Write(dstAddress, data[srcOffset]); } } for (; x < x2Trunc; x += 16, srcOffset += 16) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = _dstGpuVa + (uint)dstOffset; memoryManager.Write(dstAddress, MemoryMarshal.Cast <byte, Vector128 <byte> >(data.Slice(srcOffset, 16))[0]); } for (; x < x2; x++, srcOffset++) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = _dstGpuVa + (uint)dstOffset; memoryManager.Write(dstAddress, data[srcOffset]); } // All lines must be aligned to 4 bytes, as the data is pushed one word at a time. // If our copy length is not a multiple of 4, then we need to skip the padding bytes here. int misalignment = _lineLengthIn & 3; if (misalignment != 0) { srcOffset += 4 - misalignment; } } _context.AdvanceSequence(); } _finished = true; }
/// <summary> /// Performs actual copy of the inline data after the transfer is finished. /// </summary> private void FinishTransfer() { var memoryManager = _channel.MemoryManager; var data = MemoryMarshal.Cast <int, byte>(_buffer).Slice(0, _size); if (_isLinear && _lineCount == 1) { memoryManager.WriteTrackedResource(_dstGpuVa, data); _context.AdvanceSequence(); } else { var dstCalculator = new OffsetCalculator( _dstWidth, _dstHeight, _dstStride, _isLinear, _dstGobBlocksInY, 1); int srcOffset = 0; for (int y = _dstY; y < _dstY + _lineCount; y++) { int x1 = _dstX; int x2 = _dstX + _lineLengthIn; int x1Round = BitUtils.AlignUp(_dstX, 16); int x2Trunc = BitUtils.AlignDown(x2, 16); int x = x1; if (x1Round <= x2) { for (; x < x1Round; x++, srcOffset++) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = _dstGpuVa + (uint)dstOffset; memoryManager.Write(dstAddress, data[srcOffset]); } } for (; x < x2Trunc; x += 16, srcOffset += 16) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = _dstGpuVa + (uint)dstOffset; memoryManager.Write(dstAddress, MemoryMarshal.Cast <byte, Vector128 <byte> >(data.Slice(srcOffset, 16))[0]); } for (; x < x2; x++, srcOffset++) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = _dstGpuVa + (uint)dstOffset; memoryManager.Write(dstAddress, data[srcOffset]); } } _context.AdvanceSequence(); } _finished = true; }
/// <summary> /// Performs actual copy of the inline data after the transfer is finished. /// </summary> private void FinishTransfer() { var memoryManager = _channel.MemoryManager; var data = MemoryMarshal.Cast <int, byte>(_buffer).Slice(0, _size); if (_isLinear && _lineCount == 1) { memoryManager.WriteTrackedResource(_dstGpuVa, data.Slice(0, _lineLengthIn)); _context.AdvanceSequence(); } else { var dstCalculator = new OffsetCalculator( _dstWidth, _dstHeight, _dstStride, _isLinear, _dstGobBlocksInY, 1); int srcOffset = 0; for (int y = _dstY; y < _dstY + _lineCount; y++) { int x1 = _dstX; int x2 = _dstX + _lineLengthIn; int x1Round = BitUtils.AlignUp(_dstX, 16); int x2Trunc = BitUtils.AlignDown(x2, 16); int x = x1; if (x1Round <= x2) { for (; x < x1Round; x++, srcOffset++) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = _dstGpuVa + (uint)dstOffset; memoryManager.Write(dstAddress, data[srcOffset]); } } for (; x < x2Trunc; x += 16, srcOffset += 16) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = _dstGpuVa + (uint)dstOffset; memoryManager.Write(dstAddress, MemoryMarshal.Cast <byte, Vector128 <byte> >(data.Slice(srcOffset, 16))[0]); } for (; x < x2; x++, srcOffset++) { int dstOffset = dstCalculator.GetOffset(x, y); ulong dstAddress = _dstGpuVa + (uint)dstOffset; memoryManager.Write(dstAddress, data[srcOffset]); } // All lines must be aligned to 4 bytes, as the data is pushed one word at a time. // If our copy length is not a multiple of 4, then we need to skip the padding bytes here. int misalignment = _lineLengthIn & 3; if (misalignment != 0) { srcOffset += 4 - misalignment; } } _context.AdvanceSequence(); } _finished = true; }