コード例 #1
0
ファイル: GPFifoProcessor.cs プロジェクト: Ryujinx/Ryujinx
        /// <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();
        }
コード例 #2
0
        /// <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);
        }
コード例 #3
0
ファイル: GPFifoProcessor.cs プロジェクト: Ryujinx/Ryujinx
        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);
        }
コード例 #4
0
        /// <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);
        }