/// <summary> /// Processes a command buffer. /// </summary> /// <param name="baseGpuVa">Base GPU virtual address of the command buffer</param> /// <param name="commandBuffer">Command buffer</param> public void Process(ulong baseGpuVa, ReadOnlySpan <int> commandBuffer) { for (int index = 0; index < commandBuffer.Length; index++) { int command = commandBuffer[index]; ulong gpuVa = baseGpuVa + (ulong)index * 4; if (_state.MethodCount != 0) { if (TryFastI2mBufferUpdate(commandBuffer, ref index)) { continue; } Send(gpuVa, _state.Method, command, _state.SubChannel, _state.MethodCount <= 1); if (!_state.NonIncrementing) { _state.Method++; } if (_state.IncrementOnce) { _state.NonIncrementing = true; } _state.MethodCount--; } else { CompressedMethod meth = Unsafe.As <int, CompressedMethod>(ref command); if (TryFastUniformBufferUpdate(meth, commandBuffer, index)) { index += meth.MethodCount; continue; } switch (meth.SecOp) { case SecOp.IncMethod: case SecOp.NonIncMethod: case SecOp.OneInc: _state.Method = meth.MethodAddress; _state.SubChannel = meth.MethodSubchannel; _state.MethodCount = meth.MethodCount; _state.IncrementOnce = meth.SecOp == SecOp.OneInc; _state.NonIncrementing = meth.SecOp == SecOp.NonIncMethod; break; case SecOp.ImmdDataMethod: Send(gpuVa, meth.MethodAddress, meth.ImmdData, meth.MethodSubchannel, true); break; } } } _3dClass.FlushUboDirty(); }
/// <summary> /// Processes a command buffer. /// </summary> /// <param name="commandBuffer">Command buffer</param> public void Process(ReadOnlySpan <int> commandBuffer) { for (int index = 0; index < commandBuffer.Length; index++) { int command = commandBuffer[index]; if (_state.MethodCount != 0) { Send(new MethodParams(_state.Method, command, _state.SubChannel, _state.MethodCount)); if (!_state.NonIncrementing) { _state.Method++; } if (_state.IncrementOnce) { _state.NonIncrementing = true; } _state.MethodCount--; } else { CompressedMethod meth = Unsafe.As <int, CompressedMethod>(ref command); if (TryFastUniformBufferUpdate(meth, commandBuffer, index)) { index += meth.MethodCount; continue; } switch (meth.SecOp) { case SecOp.IncMethod: case SecOp.NonIncMethod: case SecOp.OneInc: _state.Method = meth.MethodAddress; _state.SubChannel = meth.MethodSubchannel; _state.MethodCount = meth.MethodCount; _state.IncrementOnce = meth.SecOp == SecOp.OneInc; _state.NonIncrementing = meth.SecOp == SecOp.NonIncMethod; break; case SecOp.ImmdDataMethod: Send(new MethodParams(meth.MethodAddress, meth.ImmdData, meth.MethodSubchannel, 1)); break; } } } _context.Methods.FlushUboDirty(MemoryManager); }
private bool TryFastUniformBufferUpdate(CompressedMethod meth, ReadOnlySpan <int> commandBuffer, int offset) { int availableCount = commandBuffer.Length - offset; if (meth.MethodAddress == UniformBufferUpdateDataMethodOffset && meth.MethodCount < availableCount && meth.SecOp == SecOp.NonIncMethod) { _3dClass.ConstantBufferUpdate(commandBuffer.Slice(offset + 1, meth.MethodCount)); return(true); } return(false); }
/// <summary> /// Tries to perform a fast constant buffer data update. /// If successful, all data will be copied at once, and <see cref="CompressedMethod.MethodCount"/> + 1 /// command buffer entries will be consumed. /// </summary> /// <param name="meth">Compressed method to be checked</param> /// <param name="commandBuffer">Command buffer where <paramref name="meth"/> is contained</param> /// <param name="offset">Offset at <paramref name="commandBuffer"/> where <paramref name="meth"/> is located</param> /// <returns>True if the fast copy was successful, false otherwise</returns> private bool TryFastUniformBufferUpdate(CompressedMethod meth, ReadOnlySpan <int> commandBuffer, int offset) { int availableCount = commandBuffer.Length - offset; if (meth.MethodCount < availableCount && meth.SecOp == SecOp.NonIncMethod && meth.MethodAddress == (int)MethodOffset.UniformBufferUpdateData) { GpuState state = _subChannels[meth.MethodSubchannel]; _context.Methods.UniformBufferUpdate(state, commandBuffer.Slice(offset + 1, meth.MethodCount)); return(true); } return(false); }