mirror of
https://github.com/bolucat/Archive.git
synced 2025-09-26 20:21:35 +08:00
Update On Mon May 20 20:29:43 CEST 2024
This commit is contained in:
1
.github/update.log
vendored
1
.github/update.log
vendored
@@ -652,3 +652,4 @@ Update On Thu May 16 20:28:24 CEST 2024
|
|||||||
Update On Fri May 17 20:29:52 CEST 2024
|
Update On Fri May 17 20:29:52 CEST 2024
|
||||||
Update On Sat May 18 20:30:29 CEST 2024
|
Update On Sat May 18 20:30:29 CEST 2024
|
||||||
Update On Sun May 19 20:28:25 CEST 2024
|
Update On Sun May 19 20:28:25 CEST 2024
|
||||||
|
Update On Mon May 20 20:29:32 CEST 2024
|
||||||
|
65
clash-meta/.github/workflows/build.yml
vendored
65
clash-meta/.github/workflows/build.yml
vendored
@@ -18,7 +18,7 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- Alpha
|
- Alpha
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: "${{ github.workflow }}-${{ github.ref }}"
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@@ -270,7 +270,7 @@ jobs:
|
|||||||
- name: Archive production artifacts
|
- name: Archive production artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.jobs.goos }}-${{ matrix.jobs.output }}
|
name: "${{ matrix.jobs.goos }}-${{ matrix.jobs.output }}"
|
||||||
path: |
|
path: |
|
||||||
mihomo*.gz
|
mihomo*.gz
|
||||||
mihomo*.deb
|
mihomo*.deb
|
||||||
@@ -415,35 +415,35 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
- name: Set Docker tags and labels based on trigger
|
|
||||||
id: set-meta
|
|
||||||
run: |
|
|
||||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
||||||
echo "tags=${{ github.event.inputs.version }}" >> $GITHUB_ENV
|
|
||||||
echo "labels=org.opencontainers.image.version=${{ github.event.inputs.version }}" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "tags=${{ steps.meta.outputs.tags }}" >> $GITHUB_ENV
|
|
||||||
echo "labels=${{ steps.meta.outputs.labels }}" >> $GITHUB_ENV
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# Extract metadata (tags, labels) for Docker
|
# Extract metadata (tags, labels) for Docker
|
||||||
# https://github.com/docker/metadata-action
|
# https://github.com/docker/metadata-action
|
||||||
- name: Extract Docker metadata
|
- name: Extract Docker metadata
|
||||||
id: meta
|
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||||
|
id: meta_alpha
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: ${{ env.REGISTRY }}/${{ github.repository }}
|
images: '${{ env.REGISTRY }}/${{ github.repository }}'
|
||||||
tags: ${{ env.tags }}
|
|
||||||
labels: ${{ env.labels }}
|
# Extract metadata (tags, labels) for Docker
|
||||||
|
# https://github.com/docker/metadata-action
|
||||||
|
- name: Extract Docker metadata
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }}
|
||||||
|
id: meta_release
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: '${{ env.REGISTRY }}/${{ github.repository }}'
|
||||||
|
tags: |
|
||||||
|
${{ github.event.inputs.version }}
|
||||||
|
flavor: |
|
||||||
|
latest=true
|
||||||
|
labels: org.opencontainers.image.version=${{ github.event.inputs.version }}
|
||||||
|
|
||||||
- name: Show files
|
- name: Show files
|
||||||
run: |
|
run: |
|
||||||
ls .
|
ls .
|
||||||
ls bin/
|
ls bin/
|
||||||
|
|
||||||
- name: login to docker REGISTRY
|
- name: login to docker REGISTRY
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
@@ -454,7 +454,7 @@ jobs:
|
|||||||
# Build and push Docker image with Buildx (don't push on PR)
|
# Build and push Docker image with Buildx (don't push on PR)
|
||||||
# https://github.com/docker/build-push-action
|
# https://github.com/docker/build-push-action
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
id: build-and-push
|
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
@@ -465,5 +465,20 @@ jobs:
|
|||||||
linux/amd64
|
linux/amd64
|
||||||
linux/arm64
|
linux/arm64
|
||||||
linux/arm/v7
|
linux/arm/v7
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta_alpha.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta_alpha.outputs.labels }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }}
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
platforms: |
|
||||||
|
linux/386
|
||||||
|
linux/amd64
|
||||||
|
linux/arm64
|
||||||
|
linux/arm/v7
|
||||||
|
tags: ${{ steps.meta_release.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta_release.outputs.labels }}
|
@@ -19,7 +19,7 @@ require (
|
|||||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
|
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
|
||||||
github.com/mdlayher/netlink v1.7.2
|
github.com/mdlayher/netlink v1.7.2
|
||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
||||||
github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e
|
github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136
|
||||||
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72
|
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.6
|
github.com/metacubex/sing-shadowsocks v0.2.6
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.0
|
github.com/metacubex/sing-shadowsocks2 v0.2.0
|
||||||
|
@@ -104,8 +104,8 @@ github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvO
|
|||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
||||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc=
|
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc=
|
||||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw=
|
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw=
|
||||||
github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e h1:Nzwe08FNIJpExWpy9iXkG336dN/8nJqn69yijB7vJ8g=
|
github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136 h1:Z9XGYDs6QuSqipNcxbTx+baN/bBBAIpRxVhLpoMF42U=
|
||||||
github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e/go.mod h1:uXHODgJFUfUnkkCMWLd5Er6L5QY/LFRZb9LD5jyyhsk=
|
github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136/go.mod h1:88wAATpevav4xdy5N8oejQ2cbbI6EcLYEklFeo+qywA=
|
||||||
github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1 h1:7hDHLTmjgtRoAp59STwPQpe5Pinwi4cWex+FB3Ohvco=
|
github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1 h1:7hDHLTmjgtRoAp59STwPQpe5Pinwi4cWex+FB3Ohvco=
|
||||||
github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
|
github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
|
||||||
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 h1:Wr4g1HCb5Z/QIFwFiVNjO2qL+dRu25+Mdn9xtAZZ+ew=
|
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 h1:Wr4g1HCb5Z/QIFwFiVNjO2qL+dRu25+Mdn9xtAZZ+ew=
|
||||||
|
@@ -22,7 +22,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) {
|
|||||||
quicConn.SetCongestionControl(
|
quicConn.SetCongestionControl(
|
||||||
congestion.NewCubicSender(
|
congestion.NewCubicSender(
|
||||||
congestion.DefaultClock{},
|
congestion.DefaultClock{},
|
||||||
congestion.GetInitialPacketSize(quicConn.RemoteAddr()),
|
congestion.GetInitialPacketSize(quicConn),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -30,7 +30,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) {
|
|||||||
quicConn.SetCongestionControl(
|
quicConn.SetCongestionControl(
|
||||||
congestion.NewCubicSender(
|
congestion.NewCubicSender(
|
||||||
congestion.DefaultClock{},
|
congestion.DefaultClock{},
|
||||||
congestion.GetInitialPacketSize(quicConn.RemoteAddr()),
|
congestion.GetInitialPacketSize(quicConn),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -38,7 +38,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) {
|
|||||||
quicConn.SetCongestionControl(
|
quicConn.SetCongestionControl(
|
||||||
congestion.NewBBRSender(
|
congestion.NewBBRSender(
|
||||||
congestion.DefaultClock{},
|
congestion.DefaultClock{},
|
||||||
congestion.GetInitialPacketSize(quicConn.RemoteAddr()),
|
congestion.GetInitialPacketSize(quicConn),
|
||||||
c.ByteCount(cwnd)*congestion.InitialMaxDatagramSize,
|
c.ByteCount(cwnd)*congestion.InitialMaxDatagramSize,
|
||||||
congestion.DefaultBBRMaxCongestionWindow*congestion.InitialMaxDatagramSize,
|
congestion.DefaultBBRMaxCongestionWindow*congestion.InitialMaxDatagramSize,
|
||||||
),
|
),
|
||||||
@@ -49,7 +49,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) {
|
|||||||
quicConn.SetCongestionControl(
|
quicConn.SetCongestionControl(
|
||||||
congestionv2.NewBbrSender(
|
congestionv2.NewBbrSender(
|
||||||
congestionv2.DefaultClock{},
|
congestionv2.DefaultClock{},
|
||||||
congestionv2.GetInitialPacketSize(quicConn.RemoteAddr()),
|
congestionv2.GetInitialPacketSize(quicConn),
|
||||||
c.ByteCount(cwnd),
|
c.ByteCount(cwnd),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@@ -5,34 +5,23 @@ package congestion
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/metacubex/quic-go"
|
||||||
"github.com/metacubex/quic-go/congestion"
|
"github.com/metacubex/quic-go/congestion"
|
||||||
"github.com/zhangyunhao116/fastrand"
|
"github.com/zhangyunhao116/fastrand"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// InitialMaxDatagramSize is the default maximum packet size used in QUIC for congestion window computations in bytes.
|
// InitialMaxDatagramSize is the default maximum packet size used in QUIC for congestion window computations in bytes.
|
||||||
InitialMaxDatagramSize = 1252
|
InitialMaxDatagramSize = 1280
|
||||||
InitialPacketSizeIPv4 = 1252
|
InitialPacketSize = 1280
|
||||||
InitialPacketSizeIPv6 = 1232
|
|
||||||
InitialCongestionWindow = 32
|
InitialCongestionWindow = 32
|
||||||
DefaultBBRMaxCongestionWindow = 10000
|
DefaultBBRMaxCongestionWindow = 10000
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetInitialPacketSize(addr net.Addr) congestion.ByteCount {
|
func GetInitialPacketSize(quicConn quic.Connection) congestion.ByteCount {
|
||||||
maxSize := congestion.ByteCount(1200)
|
return congestion.ByteCount(quicConn.Config().InitialPacketSize)
|
||||||
// If this is not a UDP address, we don't know anything about the MTU.
|
|
||||||
// Use the minimum size of an Initial packet as the max packet size.
|
|
||||||
if udpAddr, ok := addr.(*net.UDPAddr); ok {
|
|
||||||
if udpAddr.IP.To4() != nil {
|
|
||||||
maxSize = InitialPacketSizeIPv4
|
|
||||||
} else {
|
|
||||||
maxSize = InitialPacketSizeIPv6
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return congestion.ByteCount(maxSize)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -21,7 +21,7 @@ const (
|
|||||||
cubeCongestionWindowScale = 410
|
cubeCongestionWindowScale = 410
|
||||||
cubeFactor congestion.ByteCount = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize
|
cubeFactor congestion.ByteCount = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize
|
||||||
// TODO: when re-enabling cubic, make sure to use the actual packet size here
|
// TODO: when re-enabling cubic, make sure to use the actual packet size here
|
||||||
maxDatagramSize = congestion.ByteCount(InitialPacketSizeIPv4)
|
maxDatagramSize = congestion.ByteCount(InitialPacketSize)
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultNumConnections = 1
|
const defaultNumConnections = 1
|
||||||
|
@@ -4,9 +4,9 @@ package congestion
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/metacubex/quic-go"
|
||||||
"github.com/metacubex/quic-go/congestion"
|
"github.com/metacubex/quic-go/congestion"
|
||||||
|
|
||||||
"github.com/zhangyunhao116/fastrand"
|
"github.com/zhangyunhao116/fastrand"
|
||||||
@@ -30,7 +30,7 @@ const (
|
|||||||
// Constants based on TCP defaults.
|
// Constants based on TCP defaults.
|
||||||
// The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
|
// The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
|
||||||
// Does not inflate the pacing rate.
|
// Does not inflate the pacing rate.
|
||||||
defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSizeIPv4)
|
defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSize)
|
||||||
|
|
||||||
// The gain used for the STARTUP, equal to 2/ln(2).
|
// The gain used for the STARTUP, equal to 2/ln(2).
|
||||||
defaultHighGain = 2.885
|
defaultHighGain = 2.885
|
||||||
@@ -931,16 +931,6 @@ func bdpFromRttAndBandwidth(rtt time.Duration, bandwidth Bandwidth) congestion.B
|
|||||||
return congestion.ByteCount(rtt) * congestion.ByteCount(bandwidth) / congestion.ByteCount(BytesPerSecond) / congestion.ByteCount(time.Second)
|
return congestion.ByteCount(rtt) * congestion.ByteCount(bandwidth) / congestion.ByteCount(BytesPerSecond) / congestion.ByteCount(time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetInitialPacketSize(addr net.Addr) congestion.ByteCount {
|
func GetInitialPacketSize(quicConn quic.Connection) congestion.ByteCount {
|
||||||
// If this is not a UDP address, we don't know anything about the MTU.
|
return congestion.ByteCount(quicConn.Config().InitialPacketSize)
|
||||||
// Use the minimum size of an Initial packet as the max packet size.
|
|
||||||
if udpAddr, ok := addr.(*net.UDPAddr); ok {
|
|
||||||
if udpAddr.IP.To4() != nil {
|
|
||||||
return congestion.InitialPacketSizeIPv4
|
|
||||||
} else {
|
|
||||||
return congestion.InitialPacketSizeIPv6
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return congestion.MinInitialPacketSize
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -21,8 +21,8 @@ type Pacer struct {
|
|||||||
|
|
||||||
func NewPacer(getBandwidth func() congestion.ByteCount) *Pacer {
|
func NewPacer(getBandwidth func() congestion.ByteCount) *Pacer {
|
||||||
p := &Pacer{
|
p := &Pacer{
|
||||||
budgetAtLastSent: maxBurstPackets * congestion.InitialPacketSizeIPv4,
|
budgetAtLastSent: maxBurstPackets * congestion.InitialPacketSize,
|
||||||
maxDatagramSize: congestion.InitialPacketSizeIPv4,
|
maxDatagramSize: congestion.InitialPacketSize,
|
||||||
getBandwidth: getBandwidth,
|
getBandwidth: getBandwidth,
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
|
222
clash-nyanpasu/backend/Cargo.lock
generated
222
clash-nyanpasu/backend/Cargo.lock
generated
@@ -28,17 +28,6 @@ dependencies = [
|
|||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ahash"
|
|
||||||
version = "0.7.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom 0.2.15",
|
|
||||||
"once_cell",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.11"
|
version = "0.8.11"
|
||||||
@@ -200,7 +189,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -395,7 +384,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -430,7 +419,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -752,9 +741,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.97"
|
version = "1.0.98"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
|
checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -865,7 +854,7 @@ dependencies = [
|
|||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -887,7 +876,7 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"dashmap 5.5.3",
|
"dashmap",
|
||||||
"deelevate",
|
"deelevate",
|
||||||
"delay_timer",
|
"delay_timer",
|
||||||
"dirs 5.0.1",
|
"dirs 5.0.1",
|
||||||
@@ -903,7 +892,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"nanoid",
|
"nanoid",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"open 5.1.2",
|
"open 5.1.3",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"port_scanner",
|
"port_scanner",
|
||||||
@@ -1040,7 +1029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d"
|
checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1149,9 +1138,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.4.0"
|
version = "1.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
|
checksum = "58ebf8d6963185c7625d2c3c3962d99eb8936637b1427536d21dc36ae402ebad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
@@ -1169,9 +1158,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.12"
|
version = "0.5.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
|
checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
@@ -1197,9 +1186,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.19"
|
version = "0.8.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crunchy"
|
name = "crunchy"
|
||||||
@@ -1241,7 +1230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
|
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1251,7 +1240,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f"
|
checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1291,7 +1280,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"strsim",
|
"strsim",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1302,17 +1291,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dashmap"
|
|
||||||
version = "4.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"num_cpus",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1350,17 +1329,17 @@ checksum = "83ace6c86376be0b6cdcf3fb41882e81d94b31587573d1cfa9d01cd06bba210d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "delay_timer"
|
name = "delay_timer"
|
||||||
version = "0.11.5"
|
version = "0.11.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d70c0d5d2addc05d1e0cf7e60b3a5bf08415f03136a773d7c66b4e4a3b892cef"
|
checksum = "20eba879b7ee5f1d255d5666e16646fe384f899f71a4c0b4b0644e2e074964fe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"concat-idents",
|
"concat-idents",
|
||||||
"cron_clock",
|
"cron_clock",
|
||||||
"dashmap 4.0.2",
|
"dashmap",
|
||||||
"event-listener 2.5.3",
|
"event-listener 5.3.0",
|
||||||
"futures",
|
"futures",
|
||||||
"log",
|
"log",
|
||||||
"lru",
|
"lru",
|
||||||
@@ -1391,7 +1370,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1402,7 +1381,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1530,7 +1509,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1586,9 +1565,9 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.11.0"
|
version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
|
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embed-resource"
|
name = "embed-resource"
|
||||||
@@ -1643,7 +1622,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1880,7 +1859,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2004,7 +1983,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2442,9 +2421,6 @@ name = "hashbrown"
|
|||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
dependencies = [
|
|
||||||
"ahash 0.7.8",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
@@ -2452,7 +2428,7 @@ version = "0.14.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash 0.8.11",
|
"ahash",
|
||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2779,9 +2755,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.12"
|
version = "0.1.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
@@ -2810,7 +2786,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2849,7 +2825,7 @@ version = "0.2.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c416c05ba2a10240e022887617af3128fccdbf69713214da0fc81a5690d00df7"
|
checksum = "c416c05ba2a10240e022887617af3128fccdbf69713214da0fc81a5690d00df7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash 0.8.11",
|
"ahash",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
@@ -3093,9 +3069,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.154"
|
version = "0.2.155"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfuzzer-sys"
|
name = "libfuzzer-sys"
|
||||||
@@ -3168,9 +3144,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.13"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litrs"
|
name = "litrs"
|
||||||
@@ -3188,6 +3164,12 @@ dependencies = [
|
|||||||
"scopeguard",
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lockfree-object-pool"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.21"
|
version = "0.4.21"
|
||||||
@@ -3220,11 +3202,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lru"
|
name = "lru"
|
||||||
version = "0.7.8"
|
version = "0.12.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a"
|
checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown 0.12.3",
|
"hashbrown 0.14.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3372,9 +3354,9 @@ checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.7.2"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
|
checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adler",
|
"adler",
|
||||||
"simd-adler32",
|
"simd-adler32",
|
||||||
@@ -3599,7 +3581,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3789,9 +3771,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "open"
|
name = "open"
|
||||||
version = "5.1.2"
|
version = "5.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "449f0ff855d85ddbf1edd5b646d65249ead3f5e422aaa86b7d2d0b049b103e32"
|
checksum = "2eb49fbd5616580e9974662cb96a3463da4476e649a7e4b258df0de065db0657"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"is-wsl",
|
"is-wsl",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -3821,7 +3803,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4053,7 +4035,7 @@ dependencies = [
|
|||||||
"pest_meta",
|
"pest_meta",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4191,7 +4173,7 @@ dependencies = [
|
|||||||
"phf_shared 0.11.2",
|
"phf_shared 0.11.2",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4238,7 +4220,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4403,9 +4385,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
|
checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -4426,7 +4408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
|
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4610,9 +4592,9 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "raw-window-handle"
|
name = "raw-window-handle"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8cc3bcbdb1ddfc11e700e62968e6b4cc9c75bb466464ad28fb61c5b2c964418b"
|
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
@@ -4689,7 +4671,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4903,7 +4885,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml 0.8.26",
|
"serde_yaml 0.8.26",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4973,7 +4955,7 @@ dependencies = [
|
|||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.4.13",
|
"linux-raw-sys 0.4.14",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -5162,7 +5144,7 @@ checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5185,7 +5167,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5236,7 +5218,7 @@ dependencies = [
|
|||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5619,9 +5601,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.63"
|
version = "2.0.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704"
|
checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -6127,7 +6109,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6240,7 +6222,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6393,7 +6375,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6500,12 +6482,6 @@ version = "0.2.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typed-arena"
|
|
||||||
version = "2.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
@@ -6741,7 +6717,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -6775,7 +6751,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
@@ -7096,7 +7072,7 @@ checksum = "33082acd404763b315866e14a0d5193f3422c81086657583937a750cdd3ec340"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa 0.25.0",
|
"cocoa 0.25.0",
|
||||||
"objc",
|
"objc",
|
||||||
"raw-window-handle 0.6.1",
|
"raw-window-handle 0.6.2",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
"windows-version",
|
"windows-version",
|
||||||
]
|
]
|
||||||
@@ -7226,7 +7202,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -7237,7 +7213,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -7706,7 +7682,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
|
checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.4.13",
|
"linux-raw-sys 0.4.14",
|
||||||
"rustix 0.38.34",
|
"rustix 0.38.34",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -7754,9 +7730,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus"
|
name = "zbus"
|
||||||
version = "4.2.1"
|
version = "4.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5915716dff34abef1351d2b10305b019c8ef33dcf6c72d31a6e227d5d9d7a21"
|
checksum = "989c3977a7aafa97b12b9a35d21cdcff9b0d2289762b14683f45d66b1ba6c48f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-broadcast",
|
"async-broadcast",
|
||||||
"async-executor",
|
"async-executor",
|
||||||
@@ -7792,14 +7768,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus_macros"
|
name = "zbus_macros"
|
||||||
version = "4.2.1"
|
version = "4.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "66fceb36d0c1c4a6b98f3ce40f410e64e5a134707ed71892e1b178abc4c695d4"
|
checksum = "6fe9de53245dcf426b7be226a4217dd5e339080e5d46e64a02d6e5dcbf90fca1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate 3.1.0",
|
"proc-macro-crate 3.1.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 2.0.65",
|
||||||
"zvariant_utils",
|
"zvariant_utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -7831,7 +7807,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -7851,7 +7827,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.63",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -7913,14 +7889,16 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zopfli"
|
name = "zopfli"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c1f48f3508a3a3f2faee01629564400bc12260f6214a056d06a3aaaa6ef0736"
|
checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
|
"lockfree-object-pool",
|
||||||
"log",
|
"log",
|
||||||
|
"once_cell",
|
||||||
"simd-adler32",
|
"simd-adler32",
|
||||||
"typed-arena",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -7996,9 +7974,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant"
|
name = "zvariant"
|
||||||
version = "4.1.0"
|
version = "4.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "877ef94e5e82b231d2a309c531f191a8152baba8241a7939ee04bd76b0171308"
|
checksum = "9aa6d31a02fbfb602bfde791de7fedeb9c2c18115b3d00f3a36e489f46ffbbc7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"endi",
|
"endi",
|
||||||
"enumflags2",
|
"enumflags2",
|
||||||
@@ -8009,24 +7987,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant_derive"
|
name = "zvariant_derive"
|
||||||
version = "4.1.0"
|
version = "4.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7ca98581cc6a8120789d8f1f0997e9053837d6aa5346cbb43454d7121be6e39"
|
checksum = "642bf1b6b6d527988b3e8193d20969d53700a36eac734d21ae6639db168701c8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate 3.1.0",
|
"proc-macro-crate 3.1.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 2.0.65",
|
||||||
"zvariant_utils",
|
"zvariant_utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant_utils"
|
name = "zvariant_utils"
|
||||||
version = "1.1.1"
|
version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "75fa7291bdd68cd13c4f97cc9d78cbf16d96305856dfc7ac942aeff4c2de7d5a"
|
checksum = "fc242db087efc22bd9ade7aa7809e4ba828132edc312871584a6b4391bdf8786"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 2.0.65",
|
||||||
]
|
]
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
"@nyanpasu/ui": "workspace:^",
|
"@nyanpasu/ui": "workspace:^",
|
||||||
"@tauri-apps/api": "1.5.6",
|
"@tauri-apps/api": "1.5.6",
|
||||||
"ahooks": "3.7.11",
|
"ahooks": "3.7.11",
|
||||||
"axios": "1.6.8",
|
"axios": "1.7.1",
|
||||||
"dayjs": "1.11.11",
|
"dayjs": "1.11.11",
|
||||||
"framer-motion": "11.2.4",
|
"framer-motion": "11.2.4",
|
||||||
"i18next": "23.11.4",
|
"i18next": "23.11.4",
|
||||||
@@ -39,7 +39,6 @@
|
|||||||
"react-i18next": "14.1.1",
|
"react-i18next": "14.1.1",
|
||||||
"react-markdown": "9.0.1",
|
"react-markdown": "9.0.1",
|
||||||
"react-router-dom": "6.23.1",
|
"react-router-dom": "6.23.1",
|
||||||
"react-text-transition": "3.1.0",
|
|
||||||
"react-transition-group": "4.4.5",
|
"react-transition-group": "4.4.5",
|
||||||
"react-virtuoso": "4.7.10",
|
"react-virtuoso": "4.7.10",
|
||||||
"swr": "2.2.5",
|
"swr": "2.2.5",
|
||||||
|
@@ -17,7 +17,7 @@ import { DelayButton, GroupList, NodeList } from "@/components/proxies";
|
|||||||
import { Public } from "@mui/icons-material";
|
import { Public } from "@mui/icons-material";
|
||||||
import { useAtom } from "jotai";
|
import { useAtom } from "jotai";
|
||||||
import { proxyGroupAtom, proxyGroupSortAtom } from "@/store";
|
import { proxyGroupAtom, proxyGroupSortAtom } from "@/store";
|
||||||
import ReactTextTransition from "react-text-transition";
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
|
|
||||||
const ContentDisplay = ({ message }: { message: string }) => (
|
const ContentDisplay = ({ message }: { message: string }) => (
|
||||||
<div className="h-full w-full flex items-center justify-center">
|
<div className="h-full w-full flex items-center justify-center">
|
||||||
@@ -33,7 +33,19 @@ const ProxyGroupName = memo(function ProxyGroupName({
|
|||||||
}: {
|
}: {
|
||||||
name: string;
|
name: string;
|
||||||
}) {
|
}) {
|
||||||
return <ReactTextTransition inline>{name}</ReactTextTransition>;
|
return (
|
||||||
|
<AnimatePresence mode="sync">
|
||||||
|
<motion.div
|
||||||
|
key={`group-name-${name}`}
|
||||||
|
className="absolute"
|
||||||
|
initial={{ x: 100, opacity: 0 }}
|
||||||
|
animate={{ x: 0, opacity: 1 }}
|
||||||
|
exit={{ x: -100, opacity: 0 }}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</motion.div>
|
||||||
|
</AnimatePresence>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const SortSelector = memo(function SortSelector() {
|
const SortSelector = memo(function SortSelector() {
|
||||||
@@ -158,7 +170,9 @@ export default function ProxyPage() {
|
|||||||
hasProxies &&
|
hasProxies &&
|
||||||
!getCurrentMode.direct && (
|
!getCurrentMode.direct && (
|
||||||
<div className="w-full flex items-center justify-between">
|
<div className="w-full flex items-center justify-between">
|
||||||
<div>{group?.name && <ProxyGroupName name={group?.name} />}</div>
|
<div className="flex items-center gap-4">
|
||||||
|
{group?.name && <ProxyGroupName name={group?.name} />}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<SortSelector />
|
<SortSelector />
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 1,
|
"manifest_version": 1,
|
||||||
"latest": {
|
"latest": {
|
||||||
"mihomo": "v1.18.5",
|
"mihomo": "v1.18.5",
|
||||||
"mihomo_alpha": "alpha-030520e",
|
"mihomo_alpha": "alpha-c504985",
|
||||||
"clash_rs": "v0.1.17",
|
"clash_rs": "v0.1.17",
|
||||||
"clash_premium": "2023-09-05-gdcc8d87"
|
"clash_premium": "2023-09-05-gdcc8d87"
|
||||||
},
|
},
|
||||||
@@ -36,5 +36,5 @@
|
|||||||
"darwin-x64": "clash-darwin-amd64-n{}.gz"
|
"darwin-x64": "clash-darwin-amd64-n{}.gz"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"updated_at": "2024-05-18T22:19:33.070Z"
|
"updated_at": "2024-05-19T22:20:18.727Z"
|
||||||
}
|
}
|
||||||
|
78
clash-nyanpasu/pnpm-lock.yaml
generated
78
clash-nyanpasu/pnpm-lock.yaml
generated
@@ -207,8 +207,8 @@ importers:
|
|||||||
specifier: 3.7.11
|
specifier: 3.7.11
|
||||||
version: 3.7.11(react@19.0.0-beta-04b058868c-20240508)
|
version: 3.7.11(react@19.0.0-beta-04b058868c-20240508)
|
||||||
axios:
|
axios:
|
||||||
specifier: 1.6.8
|
specifier: 1.7.1
|
||||||
version: 1.6.8
|
version: 1.7.1
|
||||||
dayjs:
|
dayjs:
|
||||||
specifier: 1.11.11
|
specifier: 1.11.11
|
||||||
version: 1.11.11
|
version: 1.11.11
|
||||||
@@ -251,9 +251,6 @@ importers:
|
|||||||
react-router-dom:
|
react-router-dom:
|
||||||
specifier: 6.23.1
|
specifier: 6.23.1
|
||||||
version: 6.23.1(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508)
|
version: 6.23.1(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508)
|
||||||
react-text-transition:
|
|
||||||
specifier: 3.1.0
|
|
||||||
version: 3.1.0(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508)
|
|
||||||
react-transition-group:
|
react-transition-group:
|
||||||
specifier: 4.4.5
|
specifier: 4.4.5
|
||||||
version: 4.4.5(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508)
|
version: 4.4.5(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508)
|
||||||
@@ -1248,30 +1245,6 @@ packages:
|
|||||||
'@popperjs/core@2.11.8':
|
'@popperjs/core@2.11.8':
|
||||||
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
||||||
|
|
||||||
'@react-spring/animated@9.7.3':
|
|
||||||
resolution: {integrity: sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==}
|
|
||||||
peerDependencies:
|
|
||||||
react: npm:react@beta
|
|
||||||
|
|
||||||
'@react-spring/core@9.7.3':
|
|
||||||
resolution: {integrity: sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==}
|
|
||||||
peerDependencies:
|
|
||||||
react: npm:react@beta
|
|
||||||
|
|
||||||
'@react-spring/shared@9.7.3':
|
|
||||||
resolution: {integrity: sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==}
|
|
||||||
peerDependencies:
|
|
||||||
react: npm:react@beta
|
|
||||||
|
|
||||||
'@react-spring/types@9.7.3':
|
|
||||||
resolution: {integrity: sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==}
|
|
||||||
|
|
||||||
'@react-spring/web@9.7.3':
|
|
||||||
resolution: {integrity: sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==}
|
|
||||||
peerDependencies:
|
|
||||||
react: npm:react@beta
|
|
||||||
react-dom: npm:react-dom@beta
|
|
||||||
|
|
||||||
'@remix-run/router@1.16.1':
|
'@remix-run/router@1.16.1':
|
||||||
resolution: {integrity: sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==}
|
resolution: {integrity: sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@@ -1837,8 +1810,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
|
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
axios@1.6.8:
|
axios@1.7.1:
|
||||||
resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==}
|
resolution: {integrity: sha512-+LV37nQcd1EpFalkXksWNBiA17NZ5m5/WspmHGmZmdx1qBOg/VNq/c4eRJiA9VQQHBOs+N0ZhhdU10h2TyNK7Q==}
|
||||||
|
|
||||||
babel-plugin-macros@3.1.0:
|
babel-plugin-macros@3.1.0:
|
||||||
resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
|
resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
|
||||||
@@ -4019,11 +3992,6 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: npm:react@beta
|
react: npm:react@beta
|
||||||
|
|
||||||
react-text-transition@3.1.0:
|
|
||||||
resolution: {integrity: sha512-NtXEVAXvSh78+8JAnrVjpbftzD4kPowacv4GB2Nyq9C/8ko6fSm6M/XvKWQLCaZi68i9F28b++Sp8uVThlzLyg==}
|
|
||||||
peerDependencies:
|
|
||||||
react: npm:react@beta
|
|
||||||
|
|
||||||
react-transition-group@4.4.5:
|
react-transition-group@4.4.5:
|
||||||
resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
|
resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -5723,35 +5691,6 @@ snapshots:
|
|||||||
|
|
||||||
'@popperjs/core@2.11.8': {}
|
'@popperjs/core@2.11.8': {}
|
||||||
|
|
||||||
'@react-spring/animated@9.7.3(react@19.0.0-beta-04b058868c-20240508)':
|
|
||||||
dependencies:
|
|
||||||
'@react-spring/shared': 9.7.3(react@19.0.0-beta-04b058868c-20240508)
|
|
||||||
'@react-spring/types': 9.7.3
|
|
||||||
react: 19.0.0-beta-04b058868c-20240508
|
|
||||||
|
|
||||||
'@react-spring/core@9.7.3(react@19.0.0-beta-04b058868c-20240508)':
|
|
||||||
dependencies:
|
|
||||||
'@react-spring/animated': 9.7.3(react@19.0.0-beta-04b058868c-20240508)
|
|
||||||
'@react-spring/shared': 9.7.3(react@19.0.0-beta-04b058868c-20240508)
|
|
||||||
'@react-spring/types': 9.7.3
|
|
||||||
react: 19.0.0-beta-04b058868c-20240508
|
|
||||||
|
|
||||||
'@react-spring/shared@9.7.3(react@19.0.0-beta-04b058868c-20240508)':
|
|
||||||
dependencies:
|
|
||||||
'@react-spring/types': 9.7.3
|
|
||||||
react: 19.0.0-beta-04b058868c-20240508
|
|
||||||
|
|
||||||
'@react-spring/types@9.7.3': {}
|
|
||||||
|
|
||||||
'@react-spring/web@9.7.3(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508)':
|
|
||||||
dependencies:
|
|
||||||
'@react-spring/animated': 9.7.3(react@19.0.0-beta-04b058868c-20240508)
|
|
||||||
'@react-spring/core': 9.7.3(react@19.0.0-beta-04b058868c-20240508)
|
|
||||||
'@react-spring/shared': 9.7.3(react@19.0.0-beta-04b058868c-20240508)
|
|
||||||
'@react-spring/types': 9.7.3
|
|
||||||
react: 19.0.0-beta-04b058868c-20240508
|
|
||||||
react-dom: 19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508)
|
|
||||||
|
|
||||||
'@remix-run/router@1.16.1': {}
|
'@remix-run/router@1.16.1': {}
|
||||||
|
|
||||||
'@rollup/pluginutils@5.1.0(rollup@4.17.2)':
|
'@rollup/pluginutils@5.1.0(rollup@4.17.2)':
|
||||||
@@ -6332,7 +6271,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
possible-typed-array-names: 1.0.0
|
possible-typed-array-names: 1.0.0
|
||||||
|
|
||||||
axios@1.6.8:
|
axios@1.7.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects: 1.15.6
|
follow-redirects: 1.15.6
|
||||||
form-data: 4.0.0
|
form-data: 4.0.0
|
||||||
@@ -8756,13 +8695,6 @@ snapshots:
|
|||||||
'@remix-run/router': 1.16.1
|
'@remix-run/router': 1.16.1
|
||||||
react: 19.0.0-beta-04b058868c-20240508
|
react: 19.0.0-beta-04b058868c-20240508
|
||||||
|
|
||||||
react-text-transition@3.1.0(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508):
|
|
||||||
dependencies:
|
|
||||||
'@react-spring/web': 9.7.3(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508)
|
|
||||||
react: 19.0.0-beta-04b058868c-20240508
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- react-dom
|
|
||||||
|
|
||||||
react-transition-group@4.4.5(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508):
|
react-transition-group@4.4.5(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.24.5
|
'@babel/runtime': 7.24.5
|
||||||
|
@@ -54,29 +54,32 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => {
|
|||||||
: `${metadata.destinationIP}:${metadata.destinationPort}`;
|
: `${metadata.destinationIP}:${metadata.destinationPort}`;
|
||||||
|
|
||||||
const information = [
|
const information = [
|
||||||
{ label: "Host", value: host },
|
{ label: t("Host"), value: host },
|
||||||
{ label: "Download", value: parseTraffic(data.download).join(" ") },
|
{ label: t("Downloaded"), value: parseTraffic(data.download).join(" ") },
|
||||||
{ label: "Upload", value: parseTraffic(data.upload).join(" ") },
|
{ label: t("Uploaded"), value: parseTraffic(data.upload).join(" ") },
|
||||||
{
|
{
|
||||||
label: "DL Speed",
|
label: t("DL Speed"),
|
||||||
value: parseTraffic(data.curDownload ?? -1).join(" ") + "/s",
|
value: parseTraffic(data.curDownload ?? -1).join(" ") + "/s",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "UL Speed",
|
label: t("UL Speed"),
|
||||||
value: parseTraffic(data.curUpload ?? -1).join(" ") + "/s",
|
value: parseTraffic(data.curUpload ?? -1).join(" ") + "/s",
|
||||||
},
|
},
|
||||||
{ label: "Chains", value: chains },
|
{ label: t("Chains"), value: chains },
|
||||||
{ label: "Rule", value: rule },
|
{ label: t("Rule"), value: rule },
|
||||||
{
|
{
|
||||||
label: "Process",
|
label: t("Process"),
|
||||||
value: `${metadata.process}${
|
value: `${metadata.process}${
|
||||||
metadata.processPath ? `(${metadata.processPath})` : ""
|
metadata.processPath ? `(${metadata.processPath})` : ""
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
{ label: "Time", value: dayjs(data.start).fromNow() },
|
{ label: t("Time"), value: dayjs(data.start).fromNow() },
|
||||||
{ label: "Source", value: `${metadata.sourceIP}:${metadata.sourcePort}` },
|
{
|
||||||
{ label: "Destination IP", value: metadata.destinationIP },
|
label: t("Source"),
|
||||||
{ label: "Type", value: `${metadata.type}(${metadata.network})` },
|
value: `${metadata.sourceIP}:${metadata.sourcePort}`,
|
||||||
|
},
|
||||||
|
{ label: t("Destination IP"), value: metadata.destinationIP },
|
||||||
|
{ label: t("Type"), value: `${metadata.type}(${metadata.network})` },
|
||||||
];
|
];
|
||||||
|
|
||||||
const onDelete = useLockFn(async () => deleteConnection(data.id));
|
const onDelete = useLockFn(async () => deleteConnection(data.id));
|
||||||
@@ -92,13 +95,13 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => {
|
|||||||
<Box sx={{ textAlign: "right" }}>
|
<Box sx={{ textAlign: "right" }}>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
title="Close Connection"
|
title={t("Close Connection")}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onDelete();
|
onDelete();
|
||||||
onClose?.();
|
onClose?.();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("Close")}
|
{t("Close Connection")}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@@ -7,6 +7,7 @@ import {
|
|||||||
} from "@mui/x-data-grid";
|
} from "@mui/x-data-grid";
|
||||||
import { truncateStr } from "@/utils/truncate-str";
|
import { truncateStr } from "@/utils/truncate-str";
|
||||||
import parseTraffic from "@/utils/parse-traffic";
|
import parseTraffic from "@/utils/parse-traffic";
|
||||||
|
import { t } from "i18next";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
connections: IConnectionsItem[];
|
connections: IConnectionsItem[];
|
||||||
@@ -21,10 +22,10 @@ export const ConnectionTable = (props: Props) => {
|
|||||||
>({});
|
>({});
|
||||||
|
|
||||||
const columns: GridColDef[] = [
|
const columns: GridColDef[] = [
|
||||||
{ field: "host", headerName: "Host", flex: 220, minWidth: 220 },
|
{ field: "host", headerName: t("Host"), flex: 220, minWidth: 220 },
|
||||||
{
|
{
|
||||||
field: "download",
|
field: "download",
|
||||||
headerName: "Download",
|
headerName: t("Downloaded"),
|
||||||
width: 88,
|
width: 88,
|
||||||
align: "right",
|
align: "right",
|
||||||
headerAlign: "right",
|
headerAlign: "right",
|
||||||
@@ -33,7 +34,7 @@ export const ConnectionTable = (props: Props) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: "upload",
|
field: "upload",
|
||||||
headerName: "Upload",
|
headerName: t("Uploaded"),
|
||||||
width: 88,
|
width: 88,
|
||||||
align: "right",
|
align: "right",
|
||||||
headerAlign: "right",
|
headerAlign: "right",
|
||||||
@@ -42,7 +43,7 @@ export const ConnectionTable = (props: Props) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: "dlSpeed",
|
field: "dlSpeed",
|
||||||
headerName: "DL Speed",
|
headerName: t("DL Speed"),
|
||||||
width: 88,
|
width: 88,
|
||||||
align: "right",
|
align: "right",
|
||||||
headerAlign: "right",
|
headerAlign: "right",
|
||||||
@@ -51,19 +52,19 @@ export const ConnectionTable = (props: Props) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: "ulSpeed",
|
field: "ulSpeed",
|
||||||
headerName: "UL Speed",
|
headerName: t("UL Speed"),
|
||||||
width: 88,
|
width: 88,
|
||||||
align: "right",
|
align: "right",
|
||||||
headerAlign: "right",
|
headerAlign: "right",
|
||||||
valueFormatter: (params: GridValueFormatterParams<number>) =>
|
valueFormatter: (params: GridValueFormatterParams<number>) =>
|
||||||
parseTraffic(params.value).join(" ") + "/s",
|
parseTraffic(params.value).join(" ") + "/s",
|
||||||
},
|
},
|
||||||
{ field: "chains", headerName: "Chains", flex: 360, minWidth: 360 },
|
{ field: "chains", headerName: t("Chains"), flex: 360, minWidth: 360 },
|
||||||
{ field: "rule", headerName: "Rule", flex: 300, minWidth: 250 },
|
{ field: "rule", headerName: t("Rule"), flex: 300, minWidth: 250 },
|
||||||
{ field: "process", headerName: "Process", flex: 240, minWidth: 120 },
|
{ field: "process", headerName: t("Process"), flex: 240, minWidth: 120 },
|
||||||
{
|
{
|
||||||
field: "time",
|
field: "time",
|
||||||
headerName: "Time",
|
headerName: t("Time"),
|
||||||
flex: 120,
|
flex: 120,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
align: "right",
|
align: "right",
|
||||||
@@ -74,14 +75,14 @@ export const ConnectionTable = (props: Props) => {
|
|||||||
valueFormatter: (params: GridValueFormatterParams<string>) =>
|
valueFormatter: (params: GridValueFormatterParams<string>) =>
|
||||||
dayjs(params.value).fromNow(),
|
dayjs(params.value).fromNow(),
|
||||||
},
|
},
|
||||||
{ field: "source", headerName: "Source", flex: 200, minWidth: 130 },
|
{ field: "source", headerName: t("Source"), flex: 200, minWidth: 130 },
|
||||||
{
|
{
|
||||||
field: "destinationIP",
|
field: "destinationIP",
|
||||||
headerName: "Destination IP",
|
headerName: t("Destination IP"),
|
||||||
flex: 200,
|
flex: 200,
|
||||||
minWidth: 130,
|
minWidth: 130,
|
||||||
},
|
},
|
||||||
{ field: "type", headerName: "Type", flex: 160, minWidth: 100 },
|
{ field: "type", headerName: t("Type"), flex: 160, minWidth: 100 },
|
||||||
];
|
];
|
||||||
|
|
||||||
const connRows = useMemo(() => {
|
const connRows = useMemo(() => {
|
||||||
|
@@ -30,6 +30,7 @@ const Item = styled(Box)(({ theme: { palette, typography } }) => ({
|
|||||||
},
|
},
|
||||||
"& .data": {
|
"& .data": {
|
||||||
color: palette.text.primary,
|
color: palette.text.primary,
|
||||||
|
overflowWrap: "anywhere",
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@@ -79,7 +79,7 @@ export const HotkeyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
return (
|
return (
|
||||||
<BaseDialog
|
<BaseDialog
|
||||||
open={open}
|
open={open}
|
||||||
title={t("Hotkey Viewer")}
|
title={t("Hotkey Setting")}
|
||||||
contentSx={{ width: 450, maxHeight: 330 }}
|
contentSx={{ width: 450, maxHeight: 330 }}
|
||||||
okBtn={t("Save")}
|
okBtn={t("Save")}
|
||||||
cancelBtn={t("Cancel")}
|
cancelBtn={t("Cancel")}
|
||||||
|
@@ -120,13 +120,15 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
|
|
||||||
<ListItem sx={{ padding: "5px 2px", alignItems: "start" }}>
|
<ListItem sx={{ padding: "5px 2px", alignItems: "start" }}>
|
||||||
<ListItemText primary={t("Proxy Bypass")} sx={{ padding: "3px 0" }} />
|
<ListItemText primary={t("Proxy Bypass")} sx={{ padding: "3px 0" }} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={!enabled}
|
disabled={!enabled}
|
||||||
size="small"
|
size="small"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
multiline
|
multiline
|
||||||
rows={3}
|
rows={4}
|
||||||
sx={{ width: 280 }}
|
sx={{ width: "100%" }}
|
||||||
value={value.bypass}
|
value={value.bypass}
|
||||||
placeholder={sysproxy?.bypass || `-`}
|
placeholder={sysproxy?.bypass || `-`}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
@@ -155,9 +157,17 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
|
|
||||||
<FlexBox>
|
<FlexBox>
|
||||||
<Typography className="label">{t("Bypass")}</Typography>
|
<Typography className="label">{t("Bypass")}</Typography>
|
||||||
<Typography className="value" style={{ overflowWrap: "anywhere" }}>
|
</FlexBox>
|
||||||
{sysproxy?.bypass || "-"}
|
<FlexBox>
|
||||||
</Typography>
|
<TextField
|
||||||
|
disabled={true}
|
||||||
|
size="small"
|
||||||
|
autoComplete="off"
|
||||||
|
multiline
|
||||||
|
rows={4}
|
||||||
|
sx={{ width: "100%" }}
|
||||||
|
value={sysproxy?.bypass || "-"}
|
||||||
|
/>
|
||||||
</FlexBox>
|
</FlexBox>
|
||||||
</Box>
|
</Box>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { forwardRef, useImperativeHandle, useRef, useState } from "react";
|
import { forwardRef, useImperativeHandle, useState } from "react";
|
||||||
import { useLockFn } from "ahooks";
|
import { useLockFn } from "ahooks";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
|
@@ -11,7 +11,6 @@ import { GuardState } from "./mods/guard-state";
|
|||||||
import { ServiceViewer } from "./mods/service-viewer";
|
import { ServiceViewer } from "./mods/service-viewer";
|
||||||
import { SysproxyViewer } from "./mods/sysproxy-viewer";
|
import { SysproxyViewer } from "./mods/sysproxy-viewer";
|
||||||
import { TunViewer } from "./mods/tun-viewer";
|
import { TunViewer } from "./mods/tun-viewer";
|
||||||
import getSystem from "@/utils/get-system";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onError?: (err: Error) => void;
|
onError?: (err: Error) => void;
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
"Test URL": "Test URL",
|
"Test URL": "Test URL",
|
||||||
"Test All": "Test All",
|
"Test All": "Test All",
|
||||||
|
|
||||||
|
"Paste": "Paste",
|
||||||
"Profiles": "Profiles",
|
"Profiles": "Profiles",
|
||||||
"Profile URL": "Profile URL",
|
"Profile URL": "Profile URL",
|
||||||
"Import": "Import",
|
"Import": "Import",
|
||||||
@@ -70,6 +71,19 @@
|
|||||||
"Update All": "Update All",
|
"Update All": "Update All",
|
||||||
"Update At": "Update At",
|
"Update At": "Update At",
|
||||||
|
|
||||||
|
"Host": "Host",
|
||||||
|
"Downloaded": "Downloaded",
|
||||||
|
"Uploaded": "Uploaded",
|
||||||
|
"DL Speed": "DL Speed",
|
||||||
|
"UL Speed": "UL Speed",
|
||||||
|
"Chains": "Chains",
|
||||||
|
"Rule": "Rule",
|
||||||
|
"Process": "Process",
|
||||||
|
"Time": "Time",
|
||||||
|
"Source": "Source",
|
||||||
|
"Destination IP": "Destination IP",
|
||||||
|
"Close Connection": "Close Connection",
|
||||||
|
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
"Descriptions": "Descriptions",
|
"Descriptions": "Descriptions",
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
"Test URL": "Тестовый URL",
|
"Test URL": "Тестовый URL",
|
||||||
"Test All": "Тест Все",
|
"Test All": "Тест Все",
|
||||||
|
|
||||||
|
"Paste": "Вставить",
|
||||||
"Profiles": "Профили",
|
"Profiles": "Профили",
|
||||||
"Profile URL": "URL профиля",
|
"Profile URL": "URL профиля",
|
||||||
"Import": "Импорт",
|
"Import": "Импорт",
|
||||||
@@ -70,6 +71,19 @@
|
|||||||
"Update All": "Обновить все",
|
"Update All": "Обновить все",
|
||||||
"Update At": "Обновлено в",
|
"Update At": "Обновлено в",
|
||||||
|
|
||||||
|
"Host": "Хост",
|
||||||
|
"Downloaded": "Скачано",
|
||||||
|
"Uploaded": "Загружено",
|
||||||
|
"DL Speed": "Скорость загрузки",
|
||||||
|
"UL Speed": "Скорость выгрузки",
|
||||||
|
"Chains": "Цепочки",
|
||||||
|
"Rule": "Правило",
|
||||||
|
"Process": "Процесс",
|
||||||
|
"Time": "Время подключения",
|
||||||
|
"Source": "Исходный адрес",
|
||||||
|
"Destination IP": "IP-адрес назначения",
|
||||||
|
"Close Connection": "Закрыть соединение",
|
||||||
|
|
||||||
"Type": "Тип",
|
"Type": "Тип",
|
||||||
"Name": "Название",
|
"Name": "Название",
|
||||||
"Descriptions": "Описания",
|
"Descriptions": "Описания",
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
"Test URL": "测试地址",
|
"Test URL": "测试地址",
|
||||||
"Test All": "测试全部",
|
"Test All": "测试全部",
|
||||||
|
|
||||||
|
"Paste": "粘贴",
|
||||||
"Profiles": "订阅",
|
"Profiles": "订阅",
|
||||||
"Profile URL": "订阅文件链接",
|
"Profile URL": "订阅文件链接",
|
||||||
"Import": "导入",
|
"Import": "导入",
|
||||||
@@ -70,6 +71,19 @@
|
|||||||
"Update All": "更新全部",
|
"Update All": "更新全部",
|
||||||
"Update At": "更新于",
|
"Update At": "更新于",
|
||||||
|
|
||||||
|
"Host": "主机",
|
||||||
|
"Downloaded": "下载量",
|
||||||
|
"Uploaded": "上传量",
|
||||||
|
"DL Speed": "下载速度",
|
||||||
|
"UL Speed": "上传速度",
|
||||||
|
"Chains": "链路",
|
||||||
|
"Rule": "规则",
|
||||||
|
"Process": "进程",
|
||||||
|
"Time": "连接时间",
|
||||||
|
"Source": "源地址",
|
||||||
|
"Destination IP": "目标地址",
|
||||||
|
"Close Connection": "关闭连接",
|
||||||
|
|
||||||
"Type": "类型",
|
"Type": "类型",
|
||||||
"Name": "名称",
|
"Name": "名称",
|
||||||
"Descriptions": "描述",
|
"Descriptions": "描述",
|
||||||
|
@@ -134,8 +134,12 @@ const ConnectionsPage = () => {
|
|||||||
contentStyle={{ height: "100%" }}
|
contentStyle={{ height: "100%" }}
|
||||||
header={
|
header={
|
||||||
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
|
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
|
||||||
<Box sx={{ mx: 1 }}>Download: {parseTraffic(download)}</Box>
|
<Box sx={{ mx: 1 }}>
|
||||||
<Box sx={{ mx: 1 }}>Upload: {parseTraffic(upload)}</Box>
|
{t("Downloaded")}: {parseTraffic(download)}
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ mx: 1 }}>
|
||||||
|
{t("Uploaded")}: {parseTraffic(upload)}
|
||||||
|
</Box>
|
||||||
<IconButton
|
<IconButton
|
||||||
color="inherit"
|
color="inherit"
|
||||||
size="small"
|
size="small"
|
||||||
|
@@ -1,14 +1,6 @@
|
|||||||
import { useMemo, useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import { useRecoilState } from "recoil";
|
import { useRecoilState } from "recoil";
|
||||||
import {
|
import { Box, Button, IconButton, MenuItem } from "@mui/material";
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
IconButton,
|
|
||||||
MenuItem,
|
|
||||||
Select,
|
|
||||||
SelectProps,
|
|
||||||
styled,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { Virtuoso } from "react-virtuoso";
|
import { Virtuoso } from "react-virtuoso";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
LINUX_VERSION-5.10 = .216
|
LINUX_VERSION-5.10 = .217
|
||||||
LINUX_KERNEL_HASH-5.10.216 = e310588c4b23f0959614e60f007afc20e9b1a8f296d682b041fa129f96fbe151
|
LINUX_KERNEL_HASH-5.10.217 = c52bc1ffc396c11bce335c9ee5cd55fe4213cbc1fb4026ff62bb90c864c61f62
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
LINUX_VERSION-5.4 = .275
|
LINUX_VERSION-5.4 = .276
|
||||||
LINUX_KERNEL_HASH-5.4.275 = dad2b068946f0ca0026130d7ab17601d5074d90b381379c4479314d4edf4304c
|
LINUX_KERNEL_HASH-5.4.276 = e2712ebd4421ffa5b25a366659ecfbe1b45a444027ee2fe57369676453e86e07
|
||||||
|
@@ -574,7 +574,7 @@
|
|||||||
union {
|
union {
|
||||||
--- a/net/core/skbuff.c
|
--- a/net/core/skbuff.c
|
||||||
+++ b/net/core/skbuff.c
|
+++ b/net/core/skbuff.c
|
||||||
@@ -594,13 +594,22 @@ static void skb_clone_fraglist(struct sk
|
@@ -595,13 +595,22 @@ static void skb_clone_fraglist(struct sk
|
||||||
skb_get(list);
|
skb_get(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,7 +599,7 @@
|
|||||||
kfree(head);
|
kfree(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,16 +621,27 @@ static void skb_release_data(struct sk_b
|
@@ -613,16 +622,27 @@ static void skb_release_data(struct sk_b
|
||||||
if (skb->cloned &&
|
if (skb->cloned &&
|
||||||
atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
|
atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
|
||||||
&shinfo->dataref))
|
&shinfo->dataref))
|
||||||
@@ -629,7 +629,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1002,6 +1022,7 @@ static struct sk_buff *__skb_clone(struc
|
@@ -1003,6 +1023,7 @@ static struct sk_buff *__skb_clone(struc
|
||||||
n->nohdr = 0;
|
n->nohdr = 0;
|
||||||
n->peeked = 0;
|
n->peeked = 0;
|
||||||
C(pfmemalloc);
|
C(pfmemalloc);
|
||||||
@@ -637,7 +637,7 @@
|
|||||||
n->destructor = NULL;
|
n->destructor = NULL;
|
||||||
C(tail);
|
C(tail);
|
||||||
C(end);
|
C(end);
|
||||||
@@ -3420,7 +3441,7 @@ int skb_shift(struct sk_buff *tgt, struc
|
@@ -3432,7 +3453,7 @@ int skb_shift(struct sk_buff *tgt, struc
|
||||||
fragto = &skb_shinfo(tgt)->frags[merge];
|
fragto = &skb_shinfo(tgt)->frags[merge];
|
||||||
|
|
||||||
skb_frag_size_add(fragto, skb_frag_size(fragfrom));
|
skb_frag_size_add(fragto, skb_frag_size(fragfrom));
|
||||||
@@ -646,7 +646,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reposition in the original skb */
|
/* Reposition in the original skb */
|
||||||
@@ -5204,6 +5225,20 @@ bool skb_try_coalesce(struct sk_buff *to
|
@@ -5216,6 +5237,20 @@ bool skb_try_coalesce(struct sk_buff *to
|
||||||
if (skb_cloned(to))
|
if (skb_cloned(to))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -687,7 +687,7 @@
|
|||||||
#ifdef CONFIG_SKB_EXTENSIONS
|
#ifdef CONFIG_SKB_EXTENSIONS
|
||||||
__u8 active_extensions;
|
__u8 active_extensions;
|
||||||
#endif
|
#endif
|
||||||
@@ -3030,9 +3032,15 @@ static inline void skb_frag_ref(struct s
|
@@ -3045,9 +3047,15 @@ static inline void skb_frag_ref(struct s
|
||||||
*
|
*
|
||||||
* Releases a reference on the paged fragment @frag.
|
* Releases a reference on the paged fragment @frag.
|
||||||
*/
|
*/
|
||||||
@@ -705,7 +705,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3044,7 +3052,7 @@ static inline void __skb_frag_unref(skb_
|
@@ -3059,7 +3067,7 @@ static inline void __skb_frag_unref(skb_
|
||||||
*/
|
*/
|
||||||
static inline void skb_frag_unref(struct sk_buff *skb, int f)
|
static inline void skb_frag_unref(struct sk_buff *skb, int f)
|
||||||
{
|
{
|
||||||
@@ -714,7 +714,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4643,5 +4651,12 @@ static inline u64 skb_get_kcov_handle(st
|
@@ -4658,5 +4666,12 @@ static inline u64 skb_get_kcov_handle(st
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -56,7 +56,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|||||||
|
|
||||||
--- a/net/core/skbuff.c
|
--- a/net/core/skbuff.c
|
||||||
+++ b/net/core/skbuff.c
|
+++ b/net/core/skbuff.c
|
||||||
@@ -5225,18 +5225,18 @@ bool skb_try_coalesce(struct sk_buff *to
|
@@ -5237,18 +5237,18 @@ bool skb_try_coalesce(struct sk_buff *to
|
||||||
if (skb_cloned(to))
|
if (skb_cloned(to))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@@ -49,7 +49,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
enum mv88e6xxx_frame_mode {
|
enum mv88e6xxx_frame_mode {
|
||||||
MV88E6XXX_FRAME_MODE_NORMAL,
|
MV88E6XXX_FRAME_MODE_NORMAL,
|
||||||
MV88E6XXX_FRAME_MODE_DSA,
|
MV88E6XXX_FRAME_MODE_DSA,
|
||||||
@@ -464,7 +469,9 @@ struct mv88e6xxx_ops {
|
@@ -465,7 +470,9 @@ struct mv88e6xxx_ops {
|
||||||
int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
|
int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
|
||||||
uint64_t *data);
|
uint64_t *data);
|
||||||
int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
|
int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
|
||||||
|
@@ -25,7 +25,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
|
|
||||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||||
@@ -4944,6 +4944,80 @@ static int mv88e6xxx_port_mdb_del(struct
|
@@ -4969,6 +4969,80 @@ static int mv88e6xxx_port_mdb_del(struct
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port,
|
static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port,
|
||||||
bool unicast, bool multicast)
|
bool unicast, bool multicast)
|
||||||
{
|
{
|
||||||
@@ -4998,6 +5072,8 @@ static const struct dsa_switch_ops mv88e
|
@@ -5023,6 +5097,8 @@ static const struct dsa_switch_ops mv88e
|
||||||
.port_mdb_prepare = mv88e6xxx_port_mdb_prepare,
|
.port_mdb_prepare = mv88e6xxx_port_mdb_prepare,
|
||||||
.port_mdb_add = mv88e6xxx_port_mdb_add,
|
.port_mdb_add = mv88e6xxx_port_mdb_add,
|
||||||
.port_mdb_del = mv88e6xxx_port_mdb_del,
|
.port_mdb_del = mv88e6xxx_port_mdb_del,
|
||||||
@@ -117,7 +117,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
.port_hwtstamp_set = mv88e6xxx_port_hwtstamp_set,
|
.port_hwtstamp_set = mv88e6xxx_port_hwtstamp_set,
|
||||||
--- a/drivers/net/dsa/mv88e6xxx/chip.h
|
--- a/drivers/net/dsa/mv88e6xxx/chip.h
|
||||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
|
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
|
||||||
@@ -232,6 +232,8 @@ struct mv88e6xxx_port {
|
@@ -233,6 +233,8 @@ struct mv88e6xxx_port {
|
||||||
u64 vtu_member_violation;
|
u64 vtu_member_violation;
|
||||||
u64 vtu_miss_violation;
|
u64 vtu_miss_violation;
|
||||||
u8 cmode;
|
u8 cmode;
|
||||||
@@ -126,7 +126,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
unsigned int serdes_irq;
|
unsigned int serdes_irq;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -315,6 +317,10 @@ struct mv88e6xxx_chip {
|
@@ -316,6 +318,10 @@ struct mv88e6xxx_chip {
|
||||||
u16 evcap_config;
|
u16 evcap_config;
|
||||||
u16 enable_count;
|
u16 enable_count;
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
|
|
||||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||||
@@ -5011,7 +5011,7 @@ static void mv88e6xxx_port_mirror_del(st
|
@@ -5036,7 +5036,7 @@ static void mv88e6xxx_port_mirror_del(st
|
||||||
if (chip->info->ops->set_egress_port(chip,
|
if (chip->info->ops->set_egress_port(chip,
|
||||||
direction,
|
direction,
|
||||||
dsa_upstream_port(ds,
|
dsa_upstream_port(ds,
|
||||||
|
@@ -1833,7 +1833,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
}
|
}
|
||||||
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
||||||
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
||||||
@@ -3459,10 +3459,11 @@ static int bcmgenet_probe(struct platfor
|
@@ -3467,10 +3467,11 @@ static int bcmgenet_probe(struct platfor
|
||||||
const struct of_device_id *of_id = NULL;
|
const struct of_device_id *of_id = NULL;
|
||||||
struct bcmgenet_priv *priv;
|
struct bcmgenet_priv *priv;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
@@ -1846,7 +1846,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
|
|
||||||
/* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */
|
/* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */
|
||||||
dev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1,
|
dev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1,
|
||||||
@@ -3489,14 +3490,15 @@ static int bcmgenet_probe(struct platfor
|
@@ -3497,14 +3498,15 @@ static int bcmgenet_probe(struct platfor
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dn) {
|
if (dn) {
|
||||||
@@ -1865,7 +1865,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->base = devm_platform_ioremap_resource(pdev, 0);
|
priv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
@@ -3509,7 +3511,6 @@ static int bcmgenet_probe(struct platfor
|
@@ -3517,7 +3519,6 @@ static int bcmgenet_probe(struct platfor
|
||||||
|
|
||||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||||
dev_set_drvdata(&pdev->dev, dev);
|
dev_set_drvdata(&pdev->dev, dev);
|
||||||
|
@@ -60,7 +60,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
*/
|
*/
|
||||||
--- a/include/linux/skbuff.h
|
--- a/include/linux/skbuff.h
|
||||||
+++ b/include/linux/skbuff.h
|
+++ b/include/linux/skbuff.h
|
||||||
@@ -2728,6 +2728,10 @@ static inline int pskb_trim(struct sk_bu
|
@@ -2743,6 +2743,10 @@ static inline int pskb_trim(struct sk_bu
|
||||||
return (len < skb->len) ? __pskb_trim(skb, len) : 0;
|
return (len < skb->len) ? __pskb_trim(skb, len) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
/**
|
/**
|
||||||
* pskb_trim_unique - remove end from a paged unique (not cloned) buffer
|
* pskb_trim_unique - remove end from a paged unique (not cloned) buffer
|
||||||
* @skb: buffer to alter
|
* @skb: buffer to alter
|
||||||
@@ -2859,16 +2863,6 @@ static inline struct sk_buff *dev_alloc_
|
@@ -2874,16 +2878,6 @@ static inline struct sk_buff *dev_alloc_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -119,15 +119,15 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
trace_net_dev_start_xmit(skb, dev);
|
trace_net_dev_start_xmit(skb, dev);
|
||||||
--- a/net/core/skbuff.c
|
--- a/net/core/skbuff.c
|
||||||
+++ b/net/core/skbuff.c
|
+++ b/net/core/skbuff.c
|
||||||
@@ -60,6 +60,7 @@
|
@@ -61,6 +61,7 @@
|
||||||
#include <linux/prefetch.h>
|
|
||||||
#include <linux/if_vlan.h>
|
#include <linux/if_vlan.h>
|
||||||
#include <linux/mpls.h>
|
#include <linux/mpls.h>
|
||||||
|
#include <linux/kcov.h>
|
||||||
+#include <linux/if.h>
|
+#include <linux/if.h>
|
||||||
|
|
||||||
#include <net/protocol.h>
|
#include <net/protocol.h>
|
||||||
#include <net/dst.h>
|
#include <net/dst.h>
|
||||||
@@ -553,6 +554,22 @@ skb_fail:
|
@@ -554,6 +555,22 @@ skb_fail:
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__napi_alloc_skb);
|
EXPORT_SYMBOL(__napi_alloc_skb);
|
||||||
|
|
||||||
|
@@ -12,9 +12,9 @@
|
|||||||
struct list_head *br_ip_list);
|
struct list_head *br_ip_list);
|
||||||
--- a/include/linux/skbuff.h
|
--- a/include/linux/skbuff.h
|
||||||
+++ b/include/linux/skbuff.h
|
+++ b/include/linux/skbuff.h
|
||||||
@@ -866,6 +866,10 @@ struct sk_buff {
|
@@ -865,6 +865,10 @@ struct sk_buff {
|
||||||
|
#endif
|
||||||
__u8 scm_io_uring:1;
|
__u8 scm_io_uring:1;
|
||||||
__u8 gro_skip:1;
|
|
||||||
|
|
||||||
+#ifdef CONFIG_SHORTCUT_FE
|
+#ifdef CONFIG_SHORTCUT_FE
|
||||||
+ __u8 fast_forwarded:1;
|
+ __u8 fast_forwarded:1;
|
||||||
|
@@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
*/
|
*/
|
||||||
--- a/include/linux/skbuff.h
|
--- a/include/linux/skbuff.h
|
||||||
+++ b/include/linux/skbuff.h
|
+++ b/include/linux/skbuff.h
|
||||||
@@ -2695,6 +2695,10 @@ static inline int pskb_trim(struct sk_bu
|
@@ -2710,6 +2710,10 @@ static inline int pskb_trim(struct sk_bu
|
||||||
return (len < skb->len) ? __pskb_trim(skb, len) : 0;
|
return (len < skb->len) ? __pskb_trim(skb, len) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
/**
|
/**
|
||||||
* pskb_trim_unique - remove end from a paged unique (not cloned) buffer
|
* pskb_trim_unique - remove end from a paged unique (not cloned) buffer
|
||||||
* @skb: buffer to alter
|
* @skb: buffer to alter
|
||||||
@@ -2826,16 +2830,6 @@ static inline struct sk_buff *dev_alloc_
|
@@ -2841,16 +2845,6 @@ static inline struct sk_buff *dev_alloc_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
--- a/include/linux/skbuff.h
|
--- a/include/linux/skbuff.h
|
||||||
+++ b/include/linux/skbuff.h
|
+++ b/include/linux/skbuff.h
|
||||||
@@ -2694,7 +2694,7 @@ static inline int pskb_network_may_pull(
|
@@ -2709,7 +2709,7 @@ static inline int pskb_network_may_pull(
|
||||||
* NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
|
* NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
|
||||||
*/
|
*/
|
||||||
#ifndef NET_SKB_PAD
|
#ifndef NET_SKB_PAD
|
||||||
|
@@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
--- a/include/linux/netdevice.h
|
--- a/include/linux/netdevice.h
|
||||||
+++ b/include/linux/netdevice.h
|
+++ b/include/linux/netdevice.h
|
||||||
@@ -1995,6 +1995,8 @@ struct net_device {
|
@@ -2061,6 +2061,8 @@ struct net_device {
|
||||||
struct netdev_hw_addr_list mc;
|
struct netdev_hw_addr_list mc;
|
||||||
struct netdev_hw_addr_list dev_addrs;
|
struct netdev_hw_addr_list dev_addrs;
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
#endif
|
#endif
|
||||||
--- a/include/linux/skbuff.h
|
--- a/include/linux/skbuff.h
|
||||||
+++ b/include/linux/skbuff.h
|
+++ b/include/linux/skbuff.h
|
||||||
@@ -831,6 +831,7 @@ struct sk_buff {
|
@@ -868,6 +868,7 @@ struct sk_buff {
|
||||||
#ifdef CONFIG_NET_SCHED
|
#ifdef CONFIG_NET_SCHED
|
||||||
__u16 tc_index; /* traffic control index */
|
__u16 tc_index; /* traffic control index */
|
||||||
#endif
|
#endif
|
||||||
@@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
__wsum csum;
|
__wsum csum;
|
||||||
--- a/net/core/dev.c
|
--- a/net/core/dev.c
|
||||||
+++ b/net/core/dev.c
|
+++ b/net/core/dev.c
|
||||||
@@ -5516,6 +5516,9 @@ static enum gro_result dev_gro_receive(s
|
@@ -6081,6 +6081,9 @@ static enum gro_result dev_gro_receive(s
|
||||||
int same_flow;
|
int same_flow;
|
||||||
int grow;
|
int grow;
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
if (netif_elide_gro(skb->dev))
|
if (netif_elide_gro(skb->dev))
|
||||||
goto normal;
|
goto normal;
|
||||||
|
|
||||||
@@ -7318,6 +7321,48 @@ static void __netdev_adjacent_dev_unlink
|
@@ -8060,6 +8063,48 @@ static void __netdev_adjacent_dev_unlink
|
||||||
&upper_dev->adj_list.lower);
|
&upper_dev->adj_list.lower);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
static int __netdev_upper_dev_link(struct net_device *dev,
|
static int __netdev_upper_dev_link(struct net_device *dev,
|
||||||
struct net_device *upper_dev, bool master,
|
struct net_device *upper_dev, bool master,
|
||||||
void *upper_priv, void *upper_info,
|
void *upper_priv, void *upper_info,
|
||||||
@@ -7368,6 +7413,7 @@ static int __netdev_upper_dev_link(struc
|
@@ -8111,6 +8156,7 @@ static int __netdev_upper_dev_link(struc
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
|
ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
|
||||||
&changeupper_info.info);
|
&changeupper_info.info);
|
||||||
ret = notifier_to_errno(ret);
|
ret = notifier_to_errno(ret);
|
||||||
@@ -7461,6 +7507,7 @@ void netdev_upper_dev_unlink(struct net_
|
@@ -8207,6 +8253,7 @@ static void __netdev_upper_dev_unlink(st
|
||||||
|
|
||||||
__netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
|
__netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
|
call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
|
||||||
&changeupper_info.info);
|
&changeupper_info.info);
|
||||||
|
|
||||||
@@ -8191,6 +8238,7 @@ int dev_set_mac_address(struct net_devic
|
@@ -8993,6 +9040,7 @@ int dev_set_mac_address(struct net_devic
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
dev->addr_assign_type = NET_ADDR_SET;
|
dev->addr_assign_type = NET_ADDR_SET;
|
||||||
@@ -136,7 +136,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
/**
|
/**
|
||||||
* eth_type_trans - determine the packet's protocol ID.
|
* eth_type_trans - determine the packet's protocol ID.
|
||||||
* @skb: received socket data
|
* @skb: received socket data
|
||||||
@@ -184,6 +184,9 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
|
@@ -166,6 +178,9 @@ __be16 eth_type_trans(struct sk_buff *sk
|
||||||
|
|
||||||
eth_skb_pkt_type(skb, dev);
|
eth_skb_pkt_type(skb, dev);
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ Signed-off-by: Alexander Duyck <alexanderduyck@fb.com>
|
|||||||
|
|
||||||
--- a/net/core/skbuff.c
|
--- a/net/core/skbuff.c
|
||||||
+++ b/net/core/skbuff.c
|
+++ b/net/core/skbuff.c
|
||||||
@@ -4176,6 +4176,15 @@ int skb_gro_receive(struct sk_buff *p, s
|
@@ -4188,6 +4188,15 @@ int skb_gro_receive(struct sk_buff *p, s
|
||||||
if (unlikely(p->len + len >= 65536 || NAPI_GRO_CB(skb)->flush))
|
if (unlikely(p->len + len >= 65536 || NAPI_GRO_CB(skb)->flush))
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
--- a/include/linux/skbuff.h
|
--- a/include/linux/skbuff.h
|
||||||
+++ b/include/linux/skbuff.h
|
+++ b/include/linux/skbuff.h
|
||||||
@@ -2661,7 +2661,7 @@ static inline int pskb_network_may_pull(
|
@@ -2676,7 +2676,7 @@ static inline int pskb_network_may_pull(
|
||||||
* NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
|
* NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
|
||||||
*/
|
*/
|
||||||
#ifndef NET_SKB_PAD
|
#ifndef NET_SKB_PAD
|
||||||
|
@@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
--- a/include/linux/netdevice.h
|
--- a/include/linux/netdevice.h
|
||||||
+++ b/include/linux/netdevice.h
|
+++ b/include/linux/netdevice.h
|
||||||
@@ -1995,6 +1995,8 @@ struct net_device {
|
@@ -1999,6 +1999,8 @@ struct net_device {
|
||||||
struct netdev_hw_addr_list mc;
|
struct netdev_hw_addr_list mc;
|
||||||
struct netdev_hw_addr_list dev_addrs;
|
struct netdev_hw_addr_list dev_addrs;
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
/**
|
/**
|
||||||
* eth_type_trans - determine the packet's protocol ID.
|
* eth_type_trans - determine the packet's protocol ID.
|
||||||
* @skb: received socket data
|
* @skb: received socket data
|
||||||
@@ -184,6 +184,9 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
|
@@ -166,6 +178,9 @@ __be16 eth_type_trans(struct sk_buff *sk
|
||||||
|
|
||||||
eth_skb_pkt_type(skb, dev);
|
eth_skb_pkt_type(skb, dev);
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
|||||||
|
|
||||||
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
--- a/drivers/net/dsa/mv88e6xxx/chip.c
|
||||||
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
|
||||||
@@ -5098,6 +5098,7 @@ static int mv88e6xxx_register_switch(str
|
@@ -5123,6 +5123,7 @@ static int mv88e6xxx_register_switch(str
|
||||||
ds->ops = &mv88e6xxx_switch_ops;
|
ds->ops = &mv88e6xxx_switch_ops;
|
||||||
ds->ageing_time_min = chip->info->age_time_coeff;
|
ds->ageing_time_min = chip->info->age_time_coeff;
|
||||||
ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
|
ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
--- a/net/core/skbuff.c
|
--- a/net/core/skbuff.c
|
||||||
+++ b/net/core/skbuff.c
|
+++ b/net/core/skbuff.c
|
||||||
@@ -70,6 +70,7 @@
|
@@ -71,6 +71,7 @@
|
||||||
#include <net/xfrm.h>
|
#include <net/xfrm.h>
|
||||||
#include <net/mpls.h>
|
#include <net/mpls.h>
|
||||||
#include <net/mptcp.h>
|
#include <net/mptcp.h>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <trace/events/skb.h>
|
#include <trace/events/skb.h>
|
||||||
@@ -1686,6 +1687,9 @@ int pskb_expand_head(struct sk_buff *skb
|
@@ -1693,6 +1694,9 @@ int pskb_expand_head(struct sk_buff *skb
|
||||||
skb_shinfo(skb),
|
skb_shinfo(skb),
|
||||||
offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
|
offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
|
||||||
|
|
||||||
|
65
mihomo/.github/workflows/build.yml
vendored
65
mihomo/.github/workflows/build.yml
vendored
@@ -18,7 +18,7 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- Alpha
|
- Alpha
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: "${{ github.workflow }}-${{ github.ref }}"
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@@ -270,7 +270,7 @@ jobs:
|
|||||||
- name: Archive production artifacts
|
- name: Archive production artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.jobs.goos }}-${{ matrix.jobs.output }}
|
name: "${{ matrix.jobs.goos }}-${{ matrix.jobs.output }}"
|
||||||
path: |
|
path: |
|
||||||
mihomo*.gz
|
mihomo*.gz
|
||||||
mihomo*.deb
|
mihomo*.deb
|
||||||
@@ -415,35 +415,35 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
|
|
||||||
- name: Set Docker tags and labels based on trigger
|
|
||||||
id: set-meta
|
|
||||||
run: |
|
|
||||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
||||||
echo "tags=${{ github.event.inputs.version }}" >> $GITHUB_ENV
|
|
||||||
echo "labels=org.opencontainers.image.version=${{ github.event.inputs.version }}" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "tags=${{ steps.meta.outputs.tags }}" >> $GITHUB_ENV
|
|
||||||
echo "labels=${{ steps.meta.outputs.labels }}" >> $GITHUB_ENV
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# Extract metadata (tags, labels) for Docker
|
# Extract metadata (tags, labels) for Docker
|
||||||
# https://github.com/docker/metadata-action
|
# https://github.com/docker/metadata-action
|
||||||
- name: Extract Docker metadata
|
- name: Extract Docker metadata
|
||||||
id: meta
|
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||||
|
id: meta_alpha
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: ${{ env.REGISTRY }}/${{ github.repository }}
|
images: '${{ env.REGISTRY }}/${{ github.repository }}'
|
||||||
tags: ${{ env.tags }}
|
|
||||||
labels: ${{ env.labels }}
|
# Extract metadata (tags, labels) for Docker
|
||||||
|
# https://github.com/docker/metadata-action
|
||||||
|
- name: Extract Docker metadata
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }}
|
||||||
|
id: meta_release
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: '${{ env.REGISTRY }}/${{ github.repository }}'
|
||||||
|
tags: |
|
||||||
|
${{ github.event.inputs.version }}
|
||||||
|
flavor: |
|
||||||
|
latest=true
|
||||||
|
labels: org.opencontainers.image.version=${{ github.event.inputs.version }}
|
||||||
|
|
||||||
- name: Show files
|
- name: Show files
|
||||||
run: |
|
run: |
|
||||||
ls .
|
ls .
|
||||||
ls bin/
|
ls bin/
|
||||||
|
|
||||||
- name: login to docker REGISTRY
|
- name: login to docker REGISTRY
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
@@ -454,7 +454,7 @@ jobs:
|
|||||||
# Build and push Docker image with Buildx (don't push on PR)
|
# Build and push Docker image with Buildx (don't push on PR)
|
||||||
# https://github.com/docker/build-push-action
|
# https://github.com/docker/build-push-action
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
id: build-and-push
|
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
@@ -465,5 +465,20 @@ jobs:
|
|||||||
linux/amd64
|
linux/amd64
|
||||||
linux/arm64
|
linux/arm64
|
||||||
linux/arm/v7
|
linux/arm/v7
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta_alpha.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta_alpha.outputs.labels }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }}
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
platforms: |
|
||||||
|
linux/386
|
||||||
|
linux/amd64
|
||||||
|
linux/arm64
|
||||||
|
linux/arm/v7
|
||||||
|
tags: ${{ steps.meta_release.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta_release.outputs.labels }}
|
@@ -19,7 +19,7 @@ require (
|
|||||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
|
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
|
||||||
github.com/mdlayher/netlink v1.7.2
|
github.com/mdlayher/netlink v1.7.2
|
||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
||||||
github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e
|
github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136
|
||||||
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72
|
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.6
|
github.com/metacubex/sing-shadowsocks v0.2.6
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.0
|
github.com/metacubex/sing-shadowsocks2 v0.2.0
|
||||||
|
@@ -104,8 +104,8 @@ github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvO
|
|||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
||||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc=
|
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc=
|
||||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw=
|
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw=
|
||||||
github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e h1:Nzwe08FNIJpExWpy9iXkG336dN/8nJqn69yijB7vJ8g=
|
github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136 h1:Z9XGYDs6QuSqipNcxbTx+baN/bBBAIpRxVhLpoMF42U=
|
||||||
github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e/go.mod h1:uXHODgJFUfUnkkCMWLd5Er6L5QY/LFRZb9LD5jyyhsk=
|
github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136/go.mod h1:88wAATpevav4xdy5N8oejQ2cbbI6EcLYEklFeo+qywA=
|
||||||
github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1 h1:7hDHLTmjgtRoAp59STwPQpe5Pinwi4cWex+FB3Ohvco=
|
github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1 h1:7hDHLTmjgtRoAp59STwPQpe5Pinwi4cWex+FB3Ohvco=
|
||||||
github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
|
github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
|
||||||
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 h1:Wr4g1HCb5Z/QIFwFiVNjO2qL+dRu25+Mdn9xtAZZ+ew=
|
github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 h1:Wr4g1HCb5Z/QIFwFiVNjO2qL+dRu25+Mdn9xtAZZ+ew=
|
||||||
|
@@ -22,7 +22,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) {
|
|||||||
quicConn.SetCongestionControl(
|
quicConn.SetCongestionControl(
|
||||||
congestion.NewCubicSender(
|
congestion.NewCubicSender(
|
||||||
congestion.DefaultClock{},
|
congestion.DefaultClock{},
|
||||||
congestion.GetInitialPacketSize(quicConn.RemoteAddr()),
|
congestion.GetInitialPacketSize(quicConn),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -30,7 +30,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) {
|
|||||||
quicConn.SetCongestionControl(
|
quicConn.SetCongestionControl(
|
||||||
congestion.NewCubicSender(
|
congestion.NewCubicSender(
|
||||||
congestion.DefaultClock{},
|
congestion.DefaultClock{},
|
||||||
congestion.GetInitialPacketSize(quicConn.RemoteAddr()),
|
congestion.GetInitialPacketSize(quicConn),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -38,7 +38,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) {
|
|||||||
quicConn.SetCongestionControl(
|
quicConn.SetCongestionControl(
|
||||||
congestion.NewBBRSender(
|
congestion.NewBBRSender(
|
||||||
congestion.DefaultClock{},
|
congestion.DefaultClock{},
|
||||||
congestion.GetInitialPacketSize(quicConn.RemoteAddr()),
|
congestion.GetInitialPacketSize(quicConn),
|
||||||
c.ByteCount(cwnd)*congestion.InitialMaxDatagramSize,
|
c.ByteCount(cwnd)*congestion.InitialMaxDatagramSize,
|
||||||
congestion.DefaultBBRMaxCongestionWindow*congestion.InitialMaxDatagramSize,
|
congestion.DefaultBBRMaxCongestionWindow*congestion.InitialMaxDatagramSize,
|
||||||
),
|
),
|
||||||
@@ -49,7 +49,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) {
|
|||||||
quicConn.SetCongestionControl(
|
quicConn.SetCongestionControl(
|
||||||
congestionv2.NewBbrSender(
|
congestionv2.NewBbrSender(
|
||||||
congestionv2.DefaultClock{},
|
congestionv2.DefaultClock{},
|
||||||
congestionv2.GetInitialPacketSize(quicConn.RemoteAddr()),
|
congestionv2.GetInitialPacketSize(quicConn),
|
||||||
c.ByteCount(cwnd),
|
c.ByteCount(cwnd),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@@ -5,34 +5,23 @@ package congestion
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/metacubex/quic-go"
|
||||||
"github.com/metacubex/quic-go/congestion"
|
"github.com/metacubex/quic-go/congestion"
|
||||||
"github.com/zhangyunhao116/fastrand"
|
"github.com/zhangyunhao116/fastrand"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// InitialMaxDatagramSize is the default maximum packet size used in QUIC for congestion window computations in bytes.
|
// InitialMaxDatagramSize is the default maximum packet size used in QUIC for congestion window computations in bytes.
|
||||||
InitialMaxDatagramSize = 1252
|
InitialMaxDatagramSize = 1280
|
||||||
InitialPacketSizeIPv4 = 1252
|
InitialPacketSize = 1280
|
||||||
InitialPacketSizeIPv6 = 1232
|
|
||||||
InitialCongestionWindow = 32
|
InitialCongestionWindow = 32
|
||||||
DefaultBBRMaxCongestionWindow = 10000
|
DefaultBBRMaxCongestionWindow = 10000
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetInitialPacketSize(addr net.Addr) congestion.ByteCount {
|
func GetInitialPacketSize(quicConn quic.Connection) congestion.ByteCount {
|
||||||
maxSize := congestion.ByteCount(1200)
|
return congestion.ByteCount(quicConn.Config().InitialPacketSize)
|
||||||
// If this is not a UDP address, we don't know anything about the MTU.
|
|
||||||
// Use the minimum size of an Initial packet as the max packet size.
|
|
||||||
if udpAddr, ok := addr.(*net.UDPAddr); ok {
|
|
||||||
if udpAddr.IP.To4() != nil {
|
|
||||||
maxSize = InitialPacketSizeIPv4
|
|
||||||
} else {
|
|
||||||
maxSize = InitialPacketSizeIPv6
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return congestion.ByteCount(maxSize)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -21,7 +21,7 @@ const (
|
|||||||
cubeCongestionWindowScale = 410
|
cubeCongestionWindowScale = 410
|
||||||
cubeFactor congestion.ByteCount = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize
|
cubeFactor congestion.ByteCount = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize
|
||||||
// TODO: when re-enabling cubic, make sure to use the actual packet size here
|
// TODO: when re-enabling cubic, make sure to use the actual packet size here
|
||||||
maxDatagramSize = congestion.ByteCount(InitialPacketSizeIPv4)
|
maxDatagramSize = congestion.ByteCount(InitialPacketSize)
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultNumConnections = 1
|
const defaultNumConnections = 1
|
||||||
|
@@ -4,9 +4,9 @@ package congestion
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/metacubex/quic-go"
|
||||||
"github.com/metacubex/quic-go/congestion"
|
"github.com/metacubex/quic-go/congestion"
|
||||||
|
|
||||||
"github.com/zhangyunhao116/fastrand"
|
"github.com/zhangyunhao116/fastrand"
|
||||||
@@ -30,7 +30,7 @@ const (
|
|||||||
// Constants based on TCP defaults.
|
// Constants based on TCP defaults.
|
||||||
// The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
|
// The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
|
||||||
// Does not inflate the pacing rate.
|
// Does not inflate the pacing rate.
|
||||||
defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSizeIPv4)
|
defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSize)
|
||||||
|
|
||||||
// The gain used for the STARTUP, equal to 2/ln(2).
|
// The gain used for the STARTUP, equal to 2/ln(2).
|
||||||
defaultHighGain = 2.885
|
defaultHighGain = 2.885
|
||||||
@@ -931,16 +931,6 @@ func bdpFromRttAndBandwidth(rtt time.Duration, bandwidth Bandwidth) congestion.B
|
|||||||
return congestion.ByteCount(rtt) * congestion.ByteCount(bandwidth) / congestion.ByteCount(BytesPerSecond) / congestion.ByteCount(time.Second)
|
return congestion.ByteCount(rtt) * congestion.ByteCount(bandwidth) / congestion.ByteCount(BytesPerSecond) / congestion.ByteCount(time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetInitialPacketSize(addr net.Addr) congestion.ByteCount {
|
func GetInitialPacketSize(quicConn quic.Connection) congestion.ByteCount {
|
||||||
// If this is not a UDP address, we don't know anything about the MTU.
|
return congestion.ByteCount(quicConn.Config().InitialPacketSize)
|
||||||
// Use the minimum size of an Initial packet as the max packet size.
|
|
||||||
if udpAddr, ok := addr.(*net.UDPAddr); ok {
|
|
||||||
if udpAddr.IP.To4() != nil {
|
|
||||||
return congestion.InitialPacketSizeIPv4
|
|
||||||
} else {
|
|
||||||
return congestion.InitialPacketSizeIPv6
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return congestion.MinInitialPacketSize
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -21,8 +21,8 @@ type Pacer struct {
|
|||||||
|
|
||||||
func NewPacer(getBandwidth func() congestion.ByteCount) *Pacer {
|
func NewPacer(getBandwidth func() congestion.ByteCount) *Pacer {
|
||||||
p := &Pacer{
|
p := &Pacer{
|
||||||
budgetAtLastSent: maxBurstPackets * congestion.InitialPacketSizeIPv4,
|
budgetAtLastSent: maxBurstPackets * congestion.InitialPacketSize,
|
||||||
maxDatagramSize: congestion.InitialPacketSizeIPv4,
|
maxDatagramSize: congestion.InitialPacketSize,
|
||||||
getBandwidth: getBandwidth,
|
getBandwidth: getBandwidth,
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=UnblockNeteaseMusic
|
PKG_NAME:=UnblockNeteaseMusic
|
||||||
PKG_VERSION:=0.27.6-patch.1
|
PKG_VERSION:=0.27.7
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://codeload.github.com/UnblockNeteaseMusic/server/tar.gz/v${PKG_VERSION}?
|
PKG_SOURCE_URL:=https://codeload.github.com/UnblockNeteaseMusic/server/tar.gz/v${PKG_VERSION}?
|
||||||
PKG_HASH:=05b267d4f75a49e730b14505255c72dd9e6785df923e52c969ad8aa3f06380f0
|
PKG_HASH:=858f0b4dd325aefe631789b23f28ad9d3b3ea0e471af82d3a9c3d7572c92e992
|
||||||
|
|
||||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
|
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR)
|
||||||
|
@@ -6,8 +6,13 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
public enum BufferAccess
|
public enum BufferAccess
|
||||||
{
|
{
|
||||||
Default = 0,
|
Default = 0,
|
||||||
FlushPersistent = 1 << 0,
|
HostMemory = 1,
|
||||||
Stream = 1 << 1,
|
DeviceMemory = 2,
|
||||||
SparseCompatible = 1 << 2,
|
DeviceMemoryMapped = 3,
|
||||||
|
|
||||||
|
MemoryTypeMask = 0xf,
|
||||||
|
|
||||||
|
Stream = 1 << 4,
|
||||||
|
SparseCompatible = 1 << 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
{
|
{
|
||||||
public readonly TargetApi Api;
|
public readonly TargetApi Api;
|
||||||
public readonly string VendorName;
|
public readonly string VendorName;
|
||||||
|
public readonly SystemMemoryType MemoryType;
|
||||||
|
|
||||||
public readonly bool HasFrontFacingBug;
|
public readonly bool HasFrontFacingBug;
|
||||||
public readonly bool HasVectorIndexingBug;
|
public readonly bool HasVectorIndexingBug;
|
||||||
@@ -66,6 +67,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
public Capabilities(
|
public Capabilities(
|
||||||
TargetApi api,
|
TargetApi api,
|
||||||
string vendorName,
|
string vendorName,
|
||||||
|
SystemMemoryType memoryType,
|
||||||
bool hasFrontFacingBug,
|
bool hasFrontFacingBug,
|
||||||
bool hasVectorIndexingBug,
|
bool hasVectorIndexingBug,
|
||||||
bool needsFragmentOutputSpecialization,
|
bool needsFragmentOutputSpecialization,
|
||||||
@@ -120,6 +122,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
{
|
{
|
||||||
Api = api;
|
Api = api;
|
||||||
VendorName = vendorName;
|
VendorName = vendorName;
|
||||||
|
MemoryType = memoryType;
|
||||||
HasFrontFacingBug = hasFrontFacingBug;
|
HasFrontFacingBug = hasFrontFacingBug;
|
||||||
HasVectorIndexingBug = hasVectorIndexingBug;
|
HasVectorIndexingBug = hasVectorIndexingBug;
|
||||||
NeedsFragmentOutputSpecialization = needsFragmentOutputSpecialization;
|
NeedsFragmentOutputSpecialization = needsFragmentOutputSpecialization;
|
||||||
|
@@ -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, BufferAccess access = BufferAccess.Default);
|
BufferHandle CreateBuffer(int size, BufferAccess access = BufferAccess.Default);
|
||||||
BufferHandle CreateBuffer(int size, BufferAccess access, BufferHandle storageHint);
|
|
||||||
BufferHandle CreateBuffer(nint pointer, int size);
|
BufferHandle CreateBuffer(nint pointer, int size);
|
||||||
BufferHandle CreateBufferSparse(ReadOnlySpan<BufferRange> storageBuffers);
|
BufferHandle CreateBufferSparse(ReadOnlySpan<BufferRange> storageBuffers);
|
||||||
|
|
||||||
|
@@ -44,7 +44,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
}
|
}
|
||||||
|
|
||||||
Register<ActionCommand>(CommandType.Action);
|
Register<ActionCommand>(CommandType.Action);
|
||||||
Register<CreateBufferCommand>(CommandType.CreateBuffer);
|
|
||||||
Register<CreateBufferAccessCommand>(CommandType.CreateBufferAccess);
|
Register<CreateBufferAccessCommand>(CommandType.CreateBufferAccess);
|
||||||
Register<CreateBufferSparseCommand>(CommandType.CreateBufferSparse);
|
Register<CreateBufferSparseCommand>(CommandType.CreateBufferSparse);
|
||||||
Register<CreateHostBufferCommand>(CommandType.CreateHostBuffer);
|
Register<CreateHostBufferCommand>(CommandType.CreateHostBuffer);
|
||||||
|
@@ -3,7 +3,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
enum CommandType : byte
|
enum CommandType : byte
|
||||||
{
|
{
|
||||||
Action,
|
Action,
|
||||||
CreateBuffer,
|
|
||||||
CreateBufferAccess,
|
CreateBufferAccess,
|
||||||
CreateBufferSparse,
|
CreateBufferSparse,
|
||||||
CreateHostBuffer,
|
CreateHostBuffer,
|
||||||
|
@@ -1,31 +0,0 @@
|
|||||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer
|
|
||||||
{
|
|
||||||
struct CreateBufferCommand : IGALCommand, IGALCommand<CreateBufferCommand>
|
|
||||||
{
|
|
||||||
public readonly CommandType CommandType => CommandType.CreateBuffer;
|
|
||||||
private BufferHandle _threadedHandle;
|
|
||||||
private int _size;
|
|
||||||
private BufferAccess _access;
|
|
||||||
private BufferHandle _storageHint;
|
|
||||||
|
|
||||||
public void Set(BufferHandle threadedHandle, int size, BufferAccess access, BufferHandle storageHint)
|
|
||||||
{
|
|
||||||
_threadedHandle = threadedHandle;
|
|
||||||
_size = size;
|
|
||||||
_access = access;
|
|
||||||
_storageHint = storageHint;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Run(ref CreateBufferCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
|
||||||
{
|
|
||||||
BufferHandle hint = BufferHandle.Null;
|
|
||||||
|
|
||||||
if (command._storageHint != BufferHandle.Null)
|
|
||||||
{
|
|
||||||
hint = threaded.Buffers.MapBuffer(command._storageHint);
|
|
||||||
}
|
|
||||||
|
|
||||||
threaded.Buffers.AssignBuffer(command._threadedHandle, renderer.CreateBuffer(command._size, command._access, hint));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -272,15 +272,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferHandle CreateBuffer(int size, BufferAccess access, BufferHandle storageHint)
|
|
||||||
{
|
|
||||||
BufferHandle handle = Buffers.CreateBufferHandle();
|
|
||||||
New<CreateBufferCommand>().Set(handle, size, access, storageHint);
|
|
||||||
QueueCommand();
|
|
||||||
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BufferHandle CreateBuffer(nint pointer, int size)
|
public BufferHandle CreateBuffer(nint pointer, int size)
|
||||||
{
|
{
|
||||||
BufferHandle handle = Buffers.CreateBufferHandle();
|
BufferHandle handle = Buffers.CreateBufferHandle();
|
||||||
|
29
ryujinx/src/Ryujinx.Graphics.GAL/SystemMemoryType.cs
Normal file
29
ryujinx/src/Ryujinx.Graphics.GAL/SystemMemoryType.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
namespace Ryujinx.Graphics.GAL
|
||||||
|
{
|
||||||
|
public enum SystemMemoryType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The backend manages the ownership of memory. This mode never supports host imported memory.
|
||||||
|
/// </summary>
|
||||||
|
BackendManaged,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Device memory has similar performance to host memory, usually because it's shared between CPU/GPU.
|
||||||
|
/// Use host memory whenever possible.
|
||||||
|
/// </summary>
|
||||||
|
UnifiedMemory,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GPU storage to host memory goes though a slow interconnect, but it would still be preferable to use it if the data is flushed back often.
|
||||||
|
/// Assumes constant buffer access to host memory is rather fast.
|
||||||
|
/// </summary>
|
||||||
|
DedicatedMemory,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GPU storage to host memory goes though a slow interconnect, that is very slow when doing access from storage.
|
||||||
|
/// When frequently accessed, copy buffers to host memory using DMA.
|
||||||
|
/// Assumes constant buffer access to host memory is rather fast.
|
||||||
|
/// </summary>
|
||||||
|
DedicatedMemorySlowStorage
|
||||||
|
}
|
||||||
|
}
|
@@ -5,6 +5,7 @@ using Ryujinx.Graphics.GAL;
|
|||||||
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.Threed;
|
using Ryujinx.Graphics.Gpu.Engine.Threed;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.Types;
|
using Ryujinx.Graphics.Gpu.Engine.Types;
|
||||||
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
using Ryujinx.Memory.Range;
|
using Ryujinx.Memory.Range;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -495,8 +496,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
|||||||
|
|
||||||
ulong indirectBufferSize = (ulong)maxDrawCount * (ulong)stride;
|
ulong indirectBufferSize = (ulong)maxDrawCount * (ulong)stride;
|
||||||
|
|
||||||
MultiRange indirectBufferRange = bufferCache.TranslateAndCreateMultiBuffers(_processor.MemoryManager, indirectBufferGpuVa, indirectBufferSize);
|
MultiRange indirectBufferRange = bufferCache.TranslateAndCreateMultiBuffers(_processor.MemoryManager, indirectBufferGpuVa, indirectBufferSize, BufferStage.Indirect);
|
||||||
MultiRange parameterBufferRange = bufferCache.TranslateAndCreateMultiBuffers(_processor.MemoryManager, parameterBufferGpuVa, 4);
|
MultiRange parameterBufferRange = bufferCache.TranslateAndCreateMultiBuffers(_processor.MemoryManager, parameterBufferGpuVa, 4, BufferStage.Indirect);
|
||||||
|
|
||||||
_processor.ThreedClass.DrawIndirect(
|
_processor.ThreedClass.DrawIndirect(
|
||||||
topology,
|
topology,
|
||||||
|
@@ -438,7 +438,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
|
|
||||||
ReadOnlySpan<byte> dataBytes = MemoryMarshal.Cast<int, byte>(data);
|
ReadOnlySpan<byte> dataBytes = MemoryMarshal.Cast<int, byte>(data);
|
||||||
|
|
||||||
BufferHandle buffer = _context.Renderer.CreateBuffer(dataBytes.Length);
|
BufferHandle buffer = _context.Renderer.CreateBuffer(dataBytes.Length, BufferAccess.DeviceMemory);
|
||||||
_context.Renderer.SetBufferData(buffer, 0, dataBytes);
|
_context.Renderer.SetBufferData(buffer, 0, dataBytes);
|
||||||
|
|
||||||
return new IndexBuffer(buffer, count, dataBytes.Length);
|
return new IndexBuffer(buffer, count, dataBytes.Length);
|
||||||
@@ -529,7 +529,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
{
|
{
|
||||||
if (_dummyBuffer == BufferHandle.Null)
|
if (_dummyBuffer == BufferHandle.Null)
|
||||||
{
|
{
|
||||||
_dummyBuffer = _context.Renderer.CreateBuffer(DummyBufferSize);
|
_dummyBuffer = _context.Renderer.CreateBuffer(DummyBufferSize, BufferAccess.DeviceMemory);
|
||||||
_context.Renderer.Pipeline.ClearBuffer(_dummyBuffer, 0, DummyBufferSize, 0);
|
_context.Renderer.Pipeline.ClearBuffer(_dummyBuffer, 0, DummyBufferSize, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,7 +550,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
_context.Renderer.DeleteBuffer(_sequentialIndexBuffer);
|
_context.Renderer.DeleteBuffer(_sequentialIndexBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
_sequentialIndexBuffer = _context.Renderer.CreateBuffer(count * sizeof(uint));
|
_sequentialIndexBuffer = _context.Renderer.CreateBuffer(count * sizeof(uint), BufferAccess.DeviceMemory);
|
||||||
_sequentialIndexBufferCount = count;
|
_sequentialIndexBufferCount = count;
|
||||||
|
|
||||||
Span<int> data = new int[count];
|
Span<int> data = new int[count];
|
||||||
@@ -583,7 +583,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
_context.Renderer.DeleteBuffer(buffer.Handle);
|
_context.Renderer.DeleteBuffer(buffer.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.Handle = _context.Renderer.CreateBuffer(newSize);
|
buffer.Handle = _context.Renderer.CreateBuffer(newSize, BufferAccess.DeviceMemory);
|
||||||
buffer.Size = newSize;
|
buffer.Size = newSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ using Ryujinx.Common.Logging;
|
|||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.Types;
|
using Ryujinx.Graphics.Gpu.Engine.Types;
|
||||||
using Ryujinx.Graphics.Gpu.Image;
|
using Ryujinx.Graphics.Gpu.Image;
|
||||||
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
using Ryujinx.Graphics.Gpu.Shader;
|
using Ryujinx.Graphics.Gpu.Shader;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
using Ryujinx.Graphics.Shader.Translation;
|
using Ryujinx.Graphics.Shader.Translation;
|
||||||
@@ -370,7 +371,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
{
|
{
|
||||||
var memoryManager = _channel.MemoryManager;
|
var memoryManager = _channel.MemoryManager;
|
||||||
|
|
||||||
BufferRange range = memoryManager.Physical.BufferCache.GetBufferRange(memoryManager.GetPhysicalRegions(address, size));
|
BufferRange range = memoryManager.Physical.BufferCache.GetBufferRange(memoryManager.GetPhysicalRegions(address, size), BufferStage.VertexBuffer);
|
||||||
|
|
||||||
ITexture bufferTexture = _vacContext.EnsureBufferTexture(index + 2, format);
|
ITexture bufferTexture = _vacContext.EnsureBufferTexture(index + 2, format);
|
||||||
bufferTexture.SetStorage(range);
|
bufferTexture.SetStorage(range);
|
||||||
@@ -412,7 +413,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
|||||||
var memoryManager = _channel.MemoryManager;
|
var memoryManager = _channel.MemoryManager;
|
||||||
|
|
||||||
ulong misalign = address & ((ulong)_context.Capabilities.TextureBufferOffsetAlignment - 1);
|
ulong misalign = address & ((ulong)_context.Capabilities.TextureBufferOffsetAlignment - 1);
|
||||||
BufferRange range = memoryManager.Physical.BufferCache.GetBufferRange(memoryManager.GetPhysicalRegions(address + indexOffset - misalign, size + misalign));
|
BufferRange range = memoryManager.Physical.BufferCache.GetBufferRange(
|
||||||
|
memoryManager.GetPhysicalRegions(address + indexOffset - misalign, size + misalign),
|
||||||
|
BufferStage.IndexBuffer);
|
||||||
misalignedOffset = (int)misalign >> shift;
|
misalignedOffset = (int)misalign >> shift;
|
||||||
|
|
||||||
SetIndexBufferTexture(reservations, range, format);
|
SetIndexBufferTexture(reservations, range, format);
|
||||||
|
@@ -684,8 +684,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
if (hasCount)
|
if (hasCount)
|
||||||
{
|
{
|
||||||
var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferRange);
|
var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferRange, BufferStage.Indirect);
|
||||||
var parameterBuffer = memory.BufferCache.GetBufferRange(parameterBufferRange);
|
var parameterBuffer = memory.BufferCache.GetBufferRange(parameterBufferRange, BufferStage.Indirect);
|
||||||
|
|
||||||
if (indexed)
|
if (indexed)
|
||||||
{
|
{
|
||||||
@@ -698,7 +698,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferRange);
|
var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferRange, BufferStage.Indirect);
|
||||||
|
|
||||||
if (indexed)
|
if (indexed)
|
||||||
{
|
{
|
||||||
|
@@ -393,17 +393,18 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
|
|
||||||
if (force || _pendingSync || (syncpoint && SyncpointActions.Count > 0))
|
if (force || _pendingSync || (syncpoint && SyncpointActions.Count > 0))
|
||||||
{
|
{
|
||||||
Renderer.CreateSync(SyncNumber, strict);
|
|
||||||
|
|
||||||
foreach (var action in SyncActions)
|
foreach (var action in SyncActions)
|
||||||
{
|
{
|
||||||
action.SyncPreAction(syncpoint);
|
action.SyncPreAction(syncpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var action in SyncpointActions)
|
foreach (var action in SyncpointActions)
|
||||||
{
|
{
|
||||||
action.SyncPreAction(syncpoint);
|
action.SyncPreAction(syncpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Renderer.CreateSync(SyncNumber, strict);
|
||||||
|
|
||||||
SyncNumber++;
|
SyncNumber++;
|
||||||
|
|
||||||
SyncActions.RemoveAll(action => action.SyncAction(syncpoint));
|
SyncActions.RemoveAll(action => action.SyncAction(syncpoint));
|
||||||
|
@@ -708,11 +708,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
format = texture.Format;
|
format = texture.Format;
|
||||||
}
|
}
|
||||||
|
|
||||||
_channel.BufferManager.SetBufferTextureStorage(entry.ImageArray, hostTexture, texture.Range, bindingInfo, index, format);
|
_channel.BufferManager.SetBufferTextureStorage(stage, entry.ImageArray, hostTexture, texture.Range, bindingInfo, index, format);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_channel.BufferManager.SetBufferTextureStorage(entry.TextureArray, hostTexture, texture.Range, bindingInfo, index, format);
|
_channel.BufferManager.SetBufferTextureStorage(stage, entry.TextureArray, hostTexture, texture.Range, bindingInfo, index, format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isImage)
|
else if (isImage)
|
||||||
@@ -921,11 +921,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
format = texture.Format;
|
format = texture.Format;
|
||||||
}
|
}
|
||||||
|
|
||||||
_channel.BufferManager.SetBufferTextureStorage(entry.ImageArray, hostTexture, texture.Range, bindingInfo, index, format);
|
_channel.BufferManager.SetBufferTextureStorage(stage, entry.ImageArray, hostTexture, texture.Range, bindingInfo, index, format);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_channel.BufferManager.SetBufferTextureStorage(entry.TextureArray, hostTexture, texture.Range, bindingInfo, index, format);
|
_channel.BufferManager.SetBufferTextureStorage(stage, entry.TextureArray, hostTexture, texture.Range, bindingInfo, index, format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isImage)
|
else if (isImage)
|
||||||
|
@@ -645,7 +645,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_flushBuffer = _context.Renderer.CreateBuffer((int)Storage.Size, BufferAccess.FlushPersistent);
|
_flushBuffer = _context.Renderer.CreateBuffer((int)Storage.Size, BufferAccess.HostMemory);
|
||||||
_flushBufferImported = false;
|
_flushBufferImported = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,6 +10,8 @@ using System.Threading;
|
|||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Memory
|
namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
|
delegate void BufferFlushAction(ulong address, ulong size, ulong syncNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Buffer, used to store vertex and index data, uniform and storage buffers, and others.
|
/// Buffer, used to store vertex and index data, uniform and storage buffers, and others.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -23,7 +25,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Host buffer handle.
|
/// Host buffer handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BufferHandle Handle { get; }
|
public BufferHandle Handle { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start address of the buffer in guest memory.
|
/// Start address of the buffer in guest memory.
|
||||||
@@ -60,6 +62,17 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
private BufferModifiedRangeList _modifiedRanges = null;
|
private BufferModifiedRangeList _modifiedRanges = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A structure that is used to flush buffer data back to a host mapped buffer for cached readback.
|
||||||
|
/// Only used if the buffer data is explicitly owned by device local memory.
|
||||||
|
/// </summary>
|
||||||
|
private BufferPreFlush _preFlush = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Usage tracking state that determines what type of backing the buffer should use.
|
||||||
|
/// </summary>
|
||||||
|
public BufferBackingState BackingState;
|
||||||
|
|
||||||
private readonly MultiRegionHandle _memoryTrackingGranular;
|
private readonly MultiRegionHandle _memoryTrackingGranular;
|
||||||
private readonly RegionHandle _memoryTracking;
|
private readonly RegionHandle _memoryTracking;
|
||||||
|
|
||||||
@@ -87,6 +100,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="physicalMemory">Physical memory where the buffer is mapped</param>
|
/// <param name="physicalMemory">Physical memory where the buffer is mapped</param>
|
||||||
/// <param name="address">Start address of the buffer</param>
|
/// <param name="address">Start address of the buffer</param>
|
||||||
/// <param name="size">Size of the buffer in bytes</param>
|
/// <param name="size">Size of the buffer in bytes</param>
|
||||||
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
/// <param name="sparseCompatible">Indicates if the buffer can be used in a sparse buffer mapping</param>
|
/// <param name="sparseCompatible">Indicates if the buffer can be used in a sparse buffer mapping</param>
|
||||||
/// <param name="baseBuffers">Buffers which this buffer contains, and will inherit tracking handles from</param>
|
/// <param name="baseBuffers">Buffers which this buffer contains, and will inherit tracking handles from</param>
|
||||||
public Buffer(
|
public Buffer(
|
||||||
@@ -94,6 +108,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
PhysicalMemory physicalMemory,
|
PhysicalMemory physicalMemory,
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
|
BufferStage stage,
|
||||||
bool sparseCompatible,
|
bool sparseCompatible,
|
||||||
IEnumerable<Buffer> baseBuffers = null)
|
IEnumerable<Buffer> baseBuffers = null)
|
||||||
{
|
{
|
||||||
@@ -103,9 +118,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
Size = size;
|
Size = size;
|
||||||
SparseCompatible = sparseCompatible;
|
SparseCompatible = sparseCompatible;
|
||||||
|
|
||||||
BufferAccess access = sparseCompatible ? BufferAccess.SparseCompatible : BufferAccess.Default;
|
BackingState = new BufferBackingState(_context, this, stage, baseBuffers);
|
||||||
|
|
||||||
Handle = context.Renderer.CreateBuffer((int)size, access, baseBuffers?.MaxBy(x => x.Size).Handle ?? BufferHandle.Null);
|
BufferAccess access = BackingState.SwitchAccess(this);
|
||||||
|
|
||||||
|
Handle = context.Renderer.CreateBuffer((int)size, access);
|
||||||
|
|
||||||
_useGranular = size > GranularBufferThreshold;
|
_useGranular = size > GranularBufferThreshold;
|
||||||
|
|
||||||
@@ -161,6 +178,29 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
_virtualDependenciesLock = new ReaderWriterLockSlim();
|
_virtualDependenciesLock = new ReaderWriterLockSlim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recreates the backing buffer based on the desired access type
|
||||||
|
/// reported by the backing state struct.
|
||||||
|
/// </summary>
|
||||||
|
private void ChangeBacking()
|
||||||
|
{
|
||||||
|
BufferAccess access = BackingState.SwitchAccess(this);
|
||||||
|
|
||||||
|
BufferHandle newHandle = _context.Renderer.CreateBuffer((int)Size, access);
|
||||||
|
|
||||||
|
_context.Renderer.Pipeline.CopyBuffer(Handle, newHandle, 0, 0, (int)Size);
|
||||||
|
|
||||||
|
_modifiedRanges?.SelfMigration();
|
||||||
|
|
||||||
|
// If swtiching from device local to host mapped, pre-flushing data no longer makes sense.
|
||||||
|
// This is set to null and disposed when the migration fully completes.
|
||||||
|
_preFlush = null;
|
||||||
|
|
||||||
|
Handle = newHandle;
|
||||||
|
|
||||||
|
_physicalMemory.BufferCache.BufferBackingChanged(this);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a sub-range from the buffer, from a start address til a page boundary after the given size.
|
/// Gets a sub-range from the buffer, from a start address til a page boundary after the given size.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -246,6 +286,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
BackingState.RecordSet();
|
||||||
_context.Renderer.SetBufferData(Handle, 0, _physicalMemory.GetSpan(Address, (int)Size));
|
_context.Renderer.SetBufferData(Handle, 0, _physicalMemory.GetSpan(Address, (int)Size));
|
||||||
CopyToDependantVirtualBuffers();
|
CopyToDependantVirtualBuffers();
|
||||||
}
|
}
|
||||||
@@ -283,15 +324,35 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
_modifiedRanges ??= new BufferModifiedRangeList(_context, this, Flush);
|
_modifiedRanges ??= new BufferModifiedRangeList(_context, this, Flush);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a backing change is deemed necessary from the given usage.
|
||||||
|
/// If it is, queues a backing change to happen on the next sync action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stage">Buffer stage that can change backing type</param>
|
||||||
|
private void TryQueueBackingChange(BufferStage stage)
|
||||||
|
{
|
||||||
|
if (BackingState.ShouldChangeBacking(stage))
|
||||||
|
{
|
||||||
|
if (!_syncActionRegistered)
|
||||||
|
{
|
||||||
|
_context.RegisterSyncAction(this);
|
||||||
|
_syncActionRegistered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signal that the given region of the buffer has been modified.
|
/// Signal that the given region of the buffer has been modified.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">The start address of the modified region</param>
|
/// <param name="address">The start address of the modified region</param>
|
||||||
/// <param name="size">The size of the modified region</param>
|
/// <param name="size">The size of the modified region</param>
|
||||||
public void SignalModified(ulong address, ulong size)
|
/// <param name="stage">Buffer stage that triggered the modification</param>
|
||||||
|
public void SignalModified(ulong address, ulong size, BufferStage stage)
|
||||||
{
|
{
|
||||||
EnsureRangeList();
|
EnsureRangeList();
|
||||||
|
|
||||||
|
TryQueueBackingChange(stage);
|
||||||
|
|
||||||
_modifiedRanges.SignalModified(address, size);
|
_modifiedRanges.SignalModified(address, size);
|
||||||
|
|
||||||
if (!_syncActionRegistered)
|
if (!_syncActionRegistered)
|
||||||
@@ -311,6 +372,37 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
_modifiedRanges?.Clear(address, size);
|
_modifiedRanges?.Clear(address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Action to be performed immediately before sync is created.
|
||||||
|
/// This will copy any buffer ranges designated for pre-flushing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="syncpoint">True if the action is a guest syncpoint</param>
|
||||||
|
public void SyncPreAction(bool syncpoint)
|
||||||
|
{
|
||||||
|
if (_referenceCount == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackingState.ShouldChangeBacking())
|
||||||
|
{
|
||||||
|
ChangeBacking();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BackingState.IsDeviceLocal)
|
||||||
|
{
|
||||||
|
_preFlush ??= new BufferPreFlush(_context, this, FlushImpl);
|
||||||
|
|
||||||
|
if (_preFlush.ShouldCopy)
|
||||||
|
{
|
||||||
|
_modifiedRanges?.GetRangesAtSync(Address, Size, _context.SyncNumber, (address, size) =>
|
||||||
|
{
|
||||||
|
_preFlush.CopyModified(address, size);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Action to be performed when a syncpoint is reached after modification.
|
/// Action to be performed when a syncpoint is reached after modification.
|
||||||
/// This will register read/write tracking to flush the buffer from GPU when its memory is used.
|
/// This will register read/write tracking to flush the buffer from GPU when its memory is used.
|
||||||
@@ -466,6 +558,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="mSize">Size of the modified region</param>
|
/// <param name="mSize">Size of the modified region</param>
|
||||||
private void LoadRegion(ulong mAddress, ulong mSize)
|
private void LoadRegion(ulong mAddress, ulong mSize)
|
||||||
{
|
{
|
||||||
|
BackingState.RecordSet();
|
||||||
|
|
||||||
int offset = (int)(mAddress - Address);
|
int offset = (int)(mAddress - Address);
|
||||||
|
|
||||||
_context.Renderer.SetBufferData(Handle, offset, _physicalMemory.GetSpan(mAddress, (int)mSize));
|
_context.Renderer.SetBufferData(Handle, offset, _physicalMemory.GetSpan(mAddress, (int)mSize));
|
||||||
@@ -539,18 +633,84 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// Flushes a range of the buffer.
|
/// Flushes a range of the buffer.
|
||||||
/// This writes the range data back into guest memory.
|
/// This writes the range data back into guest memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="handle">Buffer handle to flush data from</param>
|
||||||
/// <param name="address">Start address of the range</param>
|
/// <param name="address">Start address of the range</param>
|
||||||
/// <param name="size">Size in bytes of the range</param>
|
/// <param name="size">Size in bytes of the range</param>
|
||||||
public void Flush(ulong address, ulong size)
|
private void FlushImpl(BufferHandle handle, ulong address, ulong size)
|
||||||
{
|
{
|
||||||
int offset = (int)(address - Address);
|
int offset = (int)(address - Address);
|
||||||
|
|
||||||
using PinnedSpan<byte> data = _context.Renderer.GetBufferData(Handle, offset, (int)size);
|
using PinnedSpan<byte> data = _context.Renderer.GetBufferData(handle, offset, (int)size);
|
||||||
|
|
||||||
// TODO: When write tracking shaders, they will need to be aware of changes in overlapping buffers.
|
// TODO: When write tracking shaders, they will need to be aware of changes in overlapping buffers.
|
||||||
_physicalMemory.WriteUntracked(address, CopyFromDependantVirtualBuffers(data.Get(), address, size));
|
_physicalMemory.WriteUntracked(address, CopyFromDependantVirtualBuffers(data.Get(), address, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flushes a range of the buffer.
|
||||||
|
/// This writes the range data back into guest memory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Start address of the range</param>
|
||||||
|
/// <param name="size">Size in bytes of the range</param>
|
||||||
|
private void FlushImpl(ulong address, ulong size)
|
||||||
|
{
|
||||||
|
FlushImpl(Handle, address, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flushes a range of the buffer from the most optimal source.
|
||||||
|
/// This writes the range data back into guest memory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Start address of the range</param>
|
||||||
|
/// <param name="size">Size in bytes of the range</param>
|
||||||
|
/// <param name="syncNumber">Sync number waited for before flushing the data</param>
|
||||||
|
public void Flush(ulong address, ulong size, ulong syncNumber)
|
||||||
|
{
|
||||||
|
BackingState.RecordFlush();
|
||||||
|
|
||||||
|
BufferPreFlush preFlush = _preFlush;
|
||||||
|
|
||||||
|
if (preFlush != null)
|
||||||
|
{
|
||||||
|
preFlush.FlushWithAction(address, size, syncNumber);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FlushImpl(address, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an action that disposes the backing buffer using its current handle.
|
||||||
|
/// Useful for deleting an old copy of the buffer after the handle changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>An action that flushes data from the specified range, using the buffer handle at the time the method is generated</returns>
|
||||||
|
public Action GetSnapshotDisposeAction()
|
||||||
|
{
|
||||||
|
BufferHandle handle = Handle;
|
||||||
|
BufferPreFlush preFlush = _preFlush;
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
_context.Renderer.DeleteBuffer(handle);
|
||||||
|
preFlush?.Dispose();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an action that flushes a range of the buffer using its current handle.
|
||||||
|
/// Useful for flushing data from old copies of the buffer after the handle changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>An action that flushes data from the specified range, using the buffer handle at the time the method is generated</returns>
|
||||||
|
public BufferFlushAction GetSnapshotFlushAction()
|
||||||
|
{
|
||||||
|
BufferHandle handle = Handle;
|
||||||
|
|
||||||
|
return (ulong address, ulong size, ulong _) =>
|
||||||
|
{
|
||||||
|
FlushImpl(handle, address, size);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Align a given address and size region to page boundaries.
|
/// Align a given address and size region to page boundaries.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -857,6 +1017,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
_modifiedRanges?.Clear();
|
_modifiedRanges?.Clear();
|
||||||
|
|
||||||
_context.Renderer.DeleteBuffer(Handle);
|
_context.Renderer.DeleteBuffer(Handle);
|
||||||
|
_preFlush?.Dispose();
|
||||||
|
_preFlush = null;
|
||||||
|
|
||||||
UnmappedSequence++;
|
UnmappedSequence++;
|
||||||
}
|
}
|
||||||
|
294
ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs
Normal file
294
ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Type of backing memory.
|
||||||
|
/// In ascending order of priority when merging multiple buffer backing states.
|
||||||
|
/// </summary>
|
||||||
|
internal enum BufferBackingType
|
||||||
|
{
|
||||||
|
HostMemory,
|
||||||
|
DeviceMemory,
|
||||||
|
DeviceMemoryWithFlush
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Keeps track of buffer usage to decide what memory heap that buffer memory is placed on.
|
||||||
|
/// Dedicated GPUs prefer certain types of resources to be device local,
|
||||||
|
/// and if we need data to be read back, we might prefer that they're in host memory.
|
||||||
|
///
|
||||||
|
/// The measurements recorded here compare to a set of heruristics (thresholds and conditions)
|
||||||
|
/// that appear to produce good performance in most software.
|
||||||
|
/// </summary>
|
||||||
|
internal struct BufferBackingState
|
||||||
|
{
|
||||||
|
private const int DeviceLocalSizeThreshold = 256 * 1024; // 256kb
|
||||||
|
|
||||||
|
private const int SetCountThreshold = 100;
|
||||||
|
private const int WriteCountThreshold = 50;
|
||||||
|
private const int FlushCountThreshold = 5;
|
||||||
|
private const int DeviceLocalForceExpiry = 100;
|
||||||
|
|
||||||
|
public readonly bool IsDeviceLocal => _activeType != BufferBackingType.HostMemory;
|
||||||
|
|
||||||
|
private readonly SystemMemoryType _systemMemoryType;
|
||||||
|
private BufferBackingType _activeType;
|
||||||
|
private BufferBackingType _desiredType;
|
||||||
|
|
||||||
|
private bool _canSwap;
|
||||||
|
|
||||||
|
private int _setCount;
|
||||||
|
private int _writeCount;
|
||||||
|
private int _flushCount;
|
||||||
|
private int _flushTemp;
|
||||||
|
private int _lastFlushWrite;
|
||||||
|
private int _deviceLocalForceCount;
|
||||||
|
|
||||||
|
private readonly int _size;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize the buffer backing state for a given parent buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">GPU context</param>
|
||||||
|
/// <param name="parent">Parent buffer</param>
|
||||||
|
/// <param name="stage">Initial buffer stage</param>
|
||||||
|
/// <param name="baseBuffers">Buffers to inherit state from</param>
|
||||||
|
public BufferBackingState(GpuContext context, Buffer parent, BufferStage stage, IEnumerable<Buffer> baseBuffers = null)
|
||||||
|
{
|
||||||
|
_size = (int)parent.Size;
|
||||||
|
_systemMemoryType = context.Capabilities.MemoryType;
|
||||||
|
|
||||||
|
// Backend managed is always auto, unified memory is always host.
|
||||||
|
_desiredType = BufferBackingType.HostMemory;
|
||||||
|
_canSwap = _systemMemoryType != SystemMemoryType.BackendManaged && _systemMemoryType != SystemMemoryType.UnifiedMemory;
|
||||||
|
|
||||||
|
if (_canSwap)
|
||||||
|
{
|
||||||
|
// Might want to start certain buffers as being device local,
|
||||||
|
// and the usage might also lock those buffers into being device local.
|
||||||
|
|
||||||
|
BufferStage storageFlags = stage & BufferStage.StorageMask;
|
||||||
|
|
||||||
|
if (parent.Size > DeviceLocalSizeThreshold && baseBuffers == null)
|
||||||
|
{
|
||||||
|
_desiredType = BufferBackingType.DeviceMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storageFlags != 0)
|
||||||
|
{
|
||||||
|
// Storage buffer bindings may require special treatment.
|
||||||
|
|
||||||
|
var rawStage = stage & BufferStage.StageMask;
|
||||||
|
|
||||||
|
if (rawStage == BufferStage.Fragment)
|
||||||
|
{
|
||||||
|
// Fragment read should start device local.
|
||||||
|
|
||||||
|
_desiredType = BufferBackingType.DeviceMemory;
|
||||||
|
|
||||||
|
if (storageFlags != BufferStage.StorageRead)
|
||||||
|
{
|
||||||
|
// Fragment write should stay device local until the use doesn't happen anymore.
|
||||||
|
|
||||||
|
_deviceLocalForceCount = DeviceLocalForceExpiry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Might be nice to force atomic access to be device local for any stage.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseBuffers != null)
|
||||||
|
{
|
||||||
|
foreach (Buffer buffer in baseBuffers)
|
||||||
|
{
|
||||||
|
CombineState(buffer.BackingState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Combine buffer backing types, selecting the one with highest priority.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">First buffer backing type</param>
|
||||||
|
/// <param name="right">Second buffer backing type</param>
|
||||||
|
/// <returns>Combined buffer backing type</returns>
|
||||||
|
private static BufferBackingType CombineTypes(BufferBackingType left, BufferBackingType right)
|
||||||
|
{
|
||||||
|
return (BufferBackingType)Math.Max((int)left, (int)right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Combine the state from the given buffer backing state with this one,
|
||||||
|
/// so that the state isn't lost when migrating buffers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="oldState">Buffer state to combine into this state</param>
|
||||||
|
private void CombineState(BufferBackingState oldState)
|
||||||
|
{
|
||||||
|
_setCount += oldState._setCount;
|
||||||
|
_writeCount += oldState._writeCount;
|
||||||
|
_flushCount += oldState._flushCount;
|
||||||
|
_flushTemp += oldState._flushTemp;
|
||||||
|
_lastFlushWrite = -1;
|
||||||
|
_deviceLocalForceCount = Math.Max(_deviceLocalForceCount, oldState._deviceLocalForceCount);
|
||||||
|
|
||||||
|
_canSwap &= oldState._canSwap;
|
||||||
|
|
||||||
|
_desiredType = CombineTypes(_desiredType, oldState._desiredType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the buffer access for the desired backing type, and record that type as now being active.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parent">Parent buffer</param>
|
||||||
|
/// <returns>Buffer access</returns>
|
||||||
|
public BufferAccess SwitchAccess(Buffer parent)
|
||||||
|
{
|
||||||
|
BufferAccess access = parent.SparseCompatible ? BufferAccess.SparseCompatible : BufferAccess.Default;
|
||||||
|
|
||||||
|
bool isBackendManaged = _systemMemoryType == SystemMemoryType.BackendManaged;
|
||||||
|
|
||||||
|
if (!isBackendManaged)
|
||||||
|
{
|
||||||
|
switch (_desiredType)
|
||||||
|
{
|
||||||
|
case BufferBackingType.HostMemory:
|
||||||
|
access |= BufferAccess.HostMemory;
|
||||||
|
break;
|
||||||
|
case BufferBackingType.DeviceMemory:
|
||||||
|
access |= BufferAccess.DeviceMemory;
|
||||||
|
break;
|
||||||
|
case BufferBackingType.DeviceMemoryWithFlush:
|
||||||
|
access |= BufferAccess.DeviceMemoryMapped;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_activeType = _desiredType;
|
||||||
|
|
||||||
|
return access;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Record when data has been uploaded to the buffer.
|
||||||
|
/// </summary>
|
||||||
|
public void RecordSet()
|
||||||
|
{
|
||||||
|
_setCount++;
|
||||||
|
|
||||||
|
ConsiderUseCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Record when data has been flushed from the buffer.
|
||||||
|
/// </summary>
|
||||||
|
public void RecordFlush()
|
||||||
|
{
|
||||||
|
if (_lastFlushWrite != _writeCount)
|
||||||
|
{
|
||||||
|
// If it's on the same page as the last flush, ignore it.
|
||||||
|
_lastFlushWrite = _writeCount;
|
||||||
|
_flushCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determine if the buffer backing should be changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the desired backing type is different from the current type</returns>
|
||||||
|
public readonly bool ShouldChangeBacking()
|
||||||
|
{
|
||||||
|
return _desiredType != _activeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determine if the buffer backing should be changed, considering a new use with the given buffer stage.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stage">Buffer stage for the use</param>
|
||||||
|
/// <returns>True if the desired backing type is different from the current type</returns>
|
||||||
|
public bool ShouldChangeBacking(BufferStage stage)
|
||||||
|
{
|
||||||
|
if (!_canSwap)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferStage storageFlags = stage & BufferStage.StorageMask;
|
||||||
|
|
||||||
|
if (storageFlags != 0)
|
||||||
|
{
|
||||||
|
if (storageFlags != BufferStage.StorageRead)
|
||||||
|
{
|
||||||
|
// Storage write.
|
||||||
|
_writeCount++;
|
||||||
|
|
||||||
|
var rawStage = stage & BufferStage.StageMask;
|
||||||
|
|
||||||
|
if (rawStage == BufferStage.Fragment)
|
||||||
|
{
|
||||||
|
// Switch to device memory, swap back only if this use disappears.
|
||||||
|
|
||||||
|
_desiredType = CombineTypes(_desiredType, BufferBackingType.DeviceMemory);
|
||||||
|
_deviceLocalForceCount = DeviceLocalForceExpiry;
|
||||||
|
|
||||||
|
// TODO: Might be nice to force atomic access to be device local for any stage.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConsiderUseCounts();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _desiredType != _activeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Evaluate the current counts to determine what the buffer's desired backing type is.
|
||||||
|
/// This method depends on heuristics devised by testing a variety of software.
|
||||||
|
/// </summary>
|
||||||
|
private void ConsiderUseCounts()
|
||||||
|
{
|
||||||
|
if (_canSwap)
|
||||||
|
{
|
||||||
|
if (_writeCount >= WriteCountThreshold || _setCount >= SetCountThreshold || _flushCount >= FlushCountThreshold)
|
||||||
|
{
|
||||||
|
if (_deviceLocalForceCount > 0 && --_deviceLocalForceCount != 0)
|
||||||
|
{
|
||||||
|
// Some buffer usage demanded that the buffer stay device local.
|
||||||
|
// The desired type was selected when this counter was set.
|
||||||
|
}
|
||||||
|
else if (_flushCount > 0 || _flushTemp-- > 0)
|
||||||
|
{
|
||||||
|
// Buffers that flush should ideally be mapped in host address space for easy copies.
|
||||||
|
// If the buffer is large it will do better on GPU memory, as there will be more writes than data flushes (typically individual pages).
|
||||||
|
// If it is small, then it's likely most of the buffer will be flushed so we want it on host memory, as access is cached.
|
||||||
|
_desiredType = _size > DeviceLocalSizeThreshold ? BufferBackingType.DeviceMemoryWithFlush : BufferBackingType.HostMemory;
|
||||||
|
}
|
||||||
|
else if (_writeCount >= WriteCountThreshold)
|
||||||
|
{
|
||||||
|
// Buffers that are written often should ideally be in the device local heap. (Storage buffers)
|
||||||
|
_desiredType = BufferBackingType.DeviceMemory;
|
||||||
|
}
|
||||||
|
else if (_setCount > SetCountThreshold)
|
||||||
|
{
|
||||||
|
// Buffers that have their data set often should ideally be host mapped. (Constant buffers)
|
||||||
|
_desiredType = BufferBackingType.HostMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's harder for a buffer that is flushed to revert to another type of mapping.
|
||||||
|
if (_flushCount > 0)
|
||||||
|
{
|
||||||
|
_flushTemp = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastFlushWrite = -1;
|
||||||
|
_flushCount = 0;
|
||||||
|
_writeCount = 0;
|
||||||
|
_setCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -107,8 +107,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
|
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
|
||||||
/// <param name="gpuVa">Start GPU virtual address of the buffer</param>
|
/// <param name="gpuVa">Start GPU virtual address of the buffer</param>
|
||||||
/// <param name="size">Size in bytes of the buffer</param>
|
/// <param name="size">Size in bytes of the buffer</param>
|
||||||
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
/// <returns>Contiguous physical range of the buffer, after address translation</returns>
|
/// <returns>Contiguous physical range of the buffer, after address translation</returns>
|
||||||
public MultiRange TranslateAndCreateBuffer(MemoryManager memoryManager, ulong gpuVa, ulong size)
|
public MultiRange TranslateAndCreateBuffer(MemoryManager memoryManager, ulong gpuVa, ulong size, BufferStage stage)
|
||||||
{
|
{
|
||||||
if (gpuVa == 0)
|
if (gpuVa == 0)
|
||||||
{
|
{
|
||||||
@@ -119,7 +120,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
if (address != MemoryManager.PteUnmapped)
|
if (address != MemoryManager.PteUnmapped)
|
||||||
{
|
{
|
||||||
CreateBuffer(address, size);
|
CreateBuffer(address, size, stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new MultiRange(address, size);
|
return new MultiRange(address, size);
|
||||||
@@ -132,8 +133,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
|
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
|
||||||
/// <param name="gpuVa">Start GPU virtual address of the buffer</param>
|
/// <param name="gpuVa">Start GPU virtual address of the buffer</param>
|
||||||
/// <param name="size">Size in bytes of the buffer</param>
|
/// <param name="size">Size in bytes of the buffer</param>
|
||||||
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
/// <returns>Physical ranges of the buffer, after address translation</returns>
|
/// <returns>Physical ranges of the buffer, after address translation</returns>
|
||||||
public MultiRange TranslateAndCreateMultiBuffers(MemoryManager memoryManager, ulong gpuVa, ulong size)
|
public MultiRange TranslateAndCreateMultiBuffers(MemoryManager memoryManager, ulong gpuVa, ulong size, BufferStage stage)
|
||||||
{
|
{
|
||||||
if (gpuVa == 0)
|
if (gpuVa == 0)
|
||||||
{
|
{
|
||||||
@@ -149,7 +151,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateBuffer(range);
|
CreateBuffer(range, stage);
|
||||||
|
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
@@ -161,8 +163,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
|
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
|
||||||
/// <param name="gpuVa">Start GPU virtual address of the buffer</param>
|
/// <param name="gpuVa">Start GPU virtual address of the buffer</param>
|
||||||
/// <param name="size">Size in bytes of the buffer</param>
|
/// <param name="size">Size in bytes of the buffer</param>
|
||||||
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
/// <returns>Physical ranges of the buffer, after address translation</returns>
|
/// <returns>Physical ranges of the buffer, after address translation</returns>
|
||||||
public MultiRange TranslateAndCreateMultiBuffersPhysicalOnly(MemoryManager memoryManager, ulong gpuVa, ulong size)
|
public MultiRange TranslateAndCreateMultiBuffersPhysicalOnly(MemoryManager memoryManager, ulong gpuVa, ulong size, BufferStage stage)
|
||||||
{
|
{
|
||||||
if (gpuVa == 0)
|
if (gpuVa == 0)
|
||||||
{
|
{
|
||||||
@@ -186,11 +189,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
{
|
{
|
||||||
if (range.Count > 1)
|
if (range.Count > 1)
|
||||||
{
|
{
|
||||||
CreateBuffer(subRange.Address, subRange.Size, SparseBufferAlignmentSize);
|
CreateBuffer(subRange.Address, subRange.Size, stage, SparseBufferAlignmentSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CreateBuffer(subRange.Address, subRange.Size);
|
CreateBuffer(subRange.Address, subRange.Size, stage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,11 +206,12 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// This can be used to ensure the existance of a buffer.
|
/// This can be used to ensure the existance of a buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="range">Physical ranges of memory where the buffer data is located</param>
|
/// <param name="range">Physical ranges of memory where the buffer data is located</param>
|
||||||
public void CreateBuffer(MultiRange range)
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
|
public void CreateBuffer(MultiRange range, BufferStage stage)
|
||||||
{
|
{
|
||||||
if (range.Count > 1)
|
if (range.Count > 1)
|
||||||
{
|
{
|
||||||
CreateMultiRangeBuffer(range);
|
CreateMultiRangeBuffer(range, stage);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -215,7 +219,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
if (subRange.Address != MemoryManager.PteUnmapped)
|
if (subRange.Address != MemoryManager.PteUnmapped)
|
||||||
{
|
{
|
||||||
CreateBuffer(subRange.Address, subRange.Size);
|
CreateBuffer(subRange.Address, subRange.Size, stage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,7 +230,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Address of the buffer in memory</param>
|
/// <param name="address">Address of the buffer in memory</param>
|
||||||
/// <param name="size">Size of the buffer in bytes</param>
|
/// <param name="size">Size of the buffer in bytes</param>
|
||||||
public void CreateBuffer(ulong address, ulong size)
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
|
public void CreateBuffer(ulong address, ulong size, BufferStage stage)
|
||||||
{
|
{
|
||||||
ulong endAddress = address + size;
|
ulong endAddress = address + size;
|
||||||
|
|
||||||
@@ -239,7 +244,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
alignedEndAddress += BufferAlignmentSize;
|
alignedEndAddress += BufferAlignmentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateBufferAligned(alignedAddress, alignedEndAddress - alignedAddress);
|
CreateBufferAligned(alignedAddress, alignedEndAddress - alignedAddress, stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -248,8 +253,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Address of the buffer in memory</param>
|
/// <param name="address">Address of the buffer in memory</param>
|
||||||
/// <param name="size">Size of the buffer in bytes</param>
|
/// <param name="size">Size of the buffer in bytes</param>
|
||||||
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
/// <param name="alignment">Alignment of the start address of the buffer in bytes</param>
|
/// <param name="alignment">Alignment of the start address of the buffer in bytes</param>
|
||||||
public void CreateBuffer(ulong address, ulong size, ulong alignment)
|
public void CreateBuffer(ulong address, ulong size, BufferStage stage, ulong alignment)
|
||||||
{
|
{
|
||||||
ulong alignmentMask = alignment - 1;
|
ulong alignmentMask = alignment - 1;
|
||||||
ulong pageAlignmentMask = BufferAlignmentMask;
|
ulong pageAlignmentMask = BufferAlignmentMask;
|
||||||
@@ -264,7 +270,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
alignedEndAddress += pageAlignmentMask;
|
alignedEndAddress += pageAlignmentMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateBufferAligned(alignedAddress, alignedEndAddress - alignedAddress, alignment);
|
CreateBufferAligned(alignedAddress, alignedEndAddress - alignedAddress, stage, alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -272,7 +278,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// if it does not exist yet.
|
/// if it does not exist yet.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="range">Physical ranges of memory</param>
|
/// <param name="range">Physical ranges of memory</param>
|
||||||
private void CreateMultiRangeBuffer(MultiRange range)
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
|
private void CreateMultiRangeBuffer(MultiRange range, BufferStage stage)
|
||||||
{
|
{
|
||||||
// Ensure all non-contiguous buffer we might use are sparse aligned.
|
// Ensure all non-contiguous buffer we might use are sparse aligned.
|
||||||
for (int i = 0; i < range.Count; i++)
|
for (int i = 0; i < range.Count; i++)
|
||||||
@@ -281,7 +288,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
if (subRange.Address != MemoryManager.PteUnmapped)
|
if (subRange.Address != MemoryManager.PteUnmapped)
|
||||||
{
|
{
|
||||||
CreateBuffer(subRange.Address, subRange.Size, SparseBufferAlignmentSize);
|
CreateBuffer(subRange.Address, subRange.Size, stage, SparseBufferAlignmentSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,9 +438,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
result.EndGpuAddress < gpuVa + size ||
|
result.EndGpuAddress < gpuVa + size ||
|
||||||
result.UnmappedSequence != result.Buffer.UnmappedSequence)
|
result.UnmappedSequence != result.Buffer.UnmappedSequence)
|
||||||
{
|
{
|
||||||
MultiRange range = TranslateAndCreateBuffer(memoryManager, gpuVa, size);
|
MultiRange range = TranslateAndCreateBuffer(memoryManager, gpuVa, size, BufferStage.Internal);
|
||||||
ulong address = range.GetSubRange(0).Address;
|
ulong address = range.GetSubRange(0).Address;
|
||||||
result = new BufferCacheEntry(address, gpuVa, GetBuffer(address, size));
|
result = new BufferCacheEntry(address, gpuVa, GetBuffer(address, size, BufferStage.Internal));
|
||||||
|
|
||||||
_dirtyCache[gpuVa] = result;
|
_dirtyCache[gpuVa] = result;
|
||||||
}
|
}
|
||||||
@@ -466,9 +473,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
result.EndGpuAddress < alignedEndGpuVa ||
|
result.EndGpuAddress < alignedEndGpuVa ||
|
||||||
result.UnmappedSequence != result.Buffer.UnmappedSequence)
|
result.UnmappedSequence != result.Buffer.UnmappedSequence)
|
||||||
{
|
{
|
||||||
MultiRange range = TranslateAndCreateBuffer(memoryManager, alignedGpuVa, size);
|
MultiRange range = TranslateAndCreateBuffer(memoryManager, alignedGpuVa, size, BufferStage.None);
|
||||||
ulong address = range.GetSubRange(0).Address;
|
ulong address = range.GetSubRange(0).Address;
|
||||||
result = new BufferCacheEntry(address, alignedGpuVa, GetBuffer(address, size));
|
result = new BufferCacheEntry(address, alignedGpuVa, GetBuffer(address, size, BufferStage.None));
|
||||||
|
|
||||||
_modifiedCache[alignedGpuVa] = result;
|
_modifiedCache[alignedGpuVa] = result;
|
||||||
}
|
}
|
||||||
@@ -485,7 +492,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Address of the buffer in guest memory</param>
|
/// <param name="address">Address of the buffer in guest memory</param>
|
||||||
/// <param name="size">Size in bytes of the buffer</param>
|
/// <param name="size">Size in bytes of the buffer</param>
|
||||||
private void CreateBufferAligned(ulong address, ulong size)
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
|
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage)
|
||||||
{
|
{
|
||||||
Buffer[] overlaps = _bufferOverlaps;
|
Buffer[] overlaps = _bufferOverlaps;
|
||||||
int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
|
int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
|
||||||
@@ -546,13 +554,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
ulong newSize = endAddress - address;
|
ulong newSize = endAddress - address;
|
||||||
|
|
||||||
CreateBufferAligned(address, newSize, anySparseCompatible, overlaps, overlapsCount);
|
CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlaps, overlapsCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No overlap, just create a new buffer.
|
// No overlap, just create a new buffer.
|
||||||
Buffer buffer = new(_context, _physicalMemory, address, size, sparseCompatible: false);
|
Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible: false);
|
||||||
|
|
||||||
lock (_buffers)
|
lock (_buffers)
|
||||||
{
|
{
|
||||||
@@ -570,8 +578,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Address of the buffer in guest memory</param>
|
/// <param name="address">Address of the buffer in guest memory</param>
|
||||||
/// <param name="size">Size in bytes of the buffer</param>
|
/// <param name="size">Size in bytes of the buffer</param>
|
||||||
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
/// <param name="alignment">Alignment of the start address of the buffer</param>
|
/// <param name="alignment">Alignment of the start address of the buffer</param>
|
||||||
private void CreateBufferAligned(ulong address, ulong size, ulong alignment)
|
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, ulong alignment)
|
||||||
{
|
{
|
||||||
Buffer[] overlaps = _bufferOverlaps;
|
Buffer[] overlaps = _bufferOverlaps;
|
||||||
int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
|
int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
|
||||||
@@ -624,13 +633,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
ulong newSize = endAddress - address;
|
ulong newSize = endAddress - address;
|
||||||
|
|
||||||
CreateBufferAligned(address, newSize, sparseAligned, overlaps, overlapsCount);
|
CreateBufferAligned(address, newSize, stage, sparseAligned, overlaps, overlapsCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No overlap, just create a new buffer.
|
// No overlap, just create a new buffer.
|
||||||
Buffer buffer = new(_context, _physicalMemory, address, size, sparseAligned);
|
Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseAligned);
|
||||||
|
|
||||||
lock (_buffers)
|
lock (_buffers)
|
||||||
{
|
{
|
||||||
@@ -648,12 +657,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Address of the buffer in guest memory</param>
|
/// <param name="address">Address of the buffer in guest memory</param>
|
||||||
/// <param name="size">Size in bytes of the buffer</param>
|
/// <param name="size">Size in bytes of the buffer</param>
|
||||||
|
/// <param name="stage">The type of usage that created the buffer</param>
|
||||||
/// <param name="sparseCompatible">Indicates if the buffer can be used in a sparse buffer mapping</param>
|
/// <param name="sparseCompatible">Indicates if the buffer can be used in a sparse buffer mapping</param>
|
||||||
/// <param name="overlaps">Buffers overlapping the range</param>
|
/// <param name="overlaps">Buffers overlapping the range</param>
|
||||||
/// <param name="overlapsCount">Total of overlaps</param>
|
/// <param name="overlapsCount">Total of overlaps</param>
|
||||||
private void CreateBufferAligned(ulong address, ulong size, bool sparseCompatible, Buffer[] overlaps, int overlapsCount)
|
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, Buffer[] overlaps, int overlapsCount)
|
||||||
{
|
{
|
||||||
Buffer newBuffer = new Buffer(_context, _physicalMemory, address, size, sparseCompatible, overlaps.Take(overlapsCount));
|
Buffer newBuffer = new Buffer(_context, _physicalMemory, address, size, stage, sparseCompatible, overlaps.Take(overlapsCount));
|
||||||
|
|
||||||
lock (_buffers)
|
lock (_buffers)
|
||||||
{
|
{
|
||||||
@@ -704,7 +714,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
for (int index = 0; index < overlapCount; index++)
|
for (int index = 0; index < overlapCount; index++)
|
||||||
{
|
{
|
||||||
CreateMultiRangeBuffer(overlaps[index].Range);
|
CreateMultiRangeBuffer(overlaps[index].Range, BufferStage.None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,8 +741,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="size">Size in bytes of the copy</param>
|
/// <param name="size">Size in bytes of the copy</param>
|
||||||
public void CopyBuffer(MemoryManager memoryManager, ulong srcVa, ulong dstVa, ulong size)
|
public void CopyBuffer(MemoryManager memoryManager, ulong srcVa, ulong dstVa, ulong size)
|
||||||
{
|
{
|
||||||
MultiRange srcRange = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, srcVa, size);
|
MultiRange srcRange = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, srcVa, size, BufferStage.Copy);
|
||||||
MultiRange dstRange = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, dstVa, size);
|
MultiRange dstRange = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, dstVa, size, BufferStage.Copy);
|
||||||
|
|
||||||
if (srcRange.Count == 1 && dstRange.Count == 1)
|
if (srcRange.Count == 1 && dstRange.Count == 1)
|
||||||
{
|
{
|
||||||
@@ -788,8 +798,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="size">Size in bytes of the copy</param>
|
/// <param name="size">Size in bytes of the copy</param>
|
||||||
private void CopyBufferSingleRange(MemoryManager memoryManager, ulong srcAddress, ulong dstAddress, ulong size)
|
private void CopyBufferSingleRange(MemoryManager memoryManager, ulong srcAddress, ulong dstAddress, ulong size)
|
||||||
{
|
{
|
||||||
Buffer srcBuffer = GetBuffer(srcAddress, size);
|
Buffer srcBuffer = GetBuffer(srcAddress, size, BufferStage.Copy);
|
||||||
Buffer dstBuffer = GetBuffer(dstAddress, size);
|
Buffer dstBuffer = GetBuffer(dstAddress, size, BufferStage.Copy);
|
||||||
|
|
||||||
int srcOffset = (int)(srcAddress - srcBuffer.Address);
|
int srcOffset = (int)(srcAddress - srcBuffer.Address);
|
||||||
int dstOffset = (int)(dstAddress - dstBuffer.Address);
|
int dstOffset = (int)(dstAddress - dstBuffer.Address);
|
||||||
@@ -803,7 +813,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
if (srcBuffer.IsModified(srcAddress, size))
|
if (srcBuffer.IsModified(srcAddress, size))
|
||||||
{
|
{
|
||||||
dstBuffer.SignalModified(dstAddress, size);
|
dstBuffer.SignalModified(dstAddress, size, BufferStage.Copy);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -828,12 +838,12 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="value">Value to be written into the buffer</param>
|
/// <param name="value">Value to be written into the buffer</param>
|
||||||
public void ClearBuffer(MemoryManager memoryManager, ulong gpuVa, ulong size, uint value)
|
public void ClearBuffer(MemoryManager memoryManager, ulong gpuVa, ulong size, uint value)
|
||||||
{
|
{
|
||||||
MultiRange range = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, gpuVa, size);
|
MultiRange range = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, gpuVa, size, BufferStage.Copy);
|
||||||
|
|
||||||
for (int index = 0; index < range.Count; index++)
|
for (int index = 0; index < range.Count; index++)
|
||||||
{
|
{
|
||||||
MemoryRange subRange = range.GetSubRange(index);
|
MemoryRange subRange = range.GetSubRange(index);
|
||||||
Buffer buffer = GetBuffer(subRange.Address, subRange.Size);
|
Buffer buffer = GetBuffer(subRange.Address, subRange.Size, BufferStage.Copy);
|
||||||
|
|
||||||
int offset = (int)(subRange.Address - buffer.Address);
|
int offset = (int)(subRange.Address - buffer.Address);
|
||||||
|
|
||||||
@@ -849,18 +859,19 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// Gets a buffer sub-range starting at a given memory address, aligned to the next page boundary.
|
/// Gets a buffer sub-range starting at a given memory address, aligned to the next page boundary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="range">Physical regions of memory where the buffer is mapped</param>
|
/// <param name="range">Physical regions of memory where the buffer is mapped</param>
|
||||||
|
/// <param name="stage">Buffer stage that triggered the access</param>
|
||||||
/// <param name="write">Whether the buffer will be written to by this use</param>
|
/// <param name="write">Whether the buffer will be written to by this use</param>
|
||||||
/// <returns>The buffer sub-range starting at the given memory address</returns>
|
/// <returns>The buffer sub-range starting at the given memory address</returns>
|
||||||
public BufferRange GetBufferRangeAligned(MultiRange range, bool write = false)
|
public BufferRange GetBufferRangeAligned(MultiRange range, BufferStage stage, bool write = false)
|
||||||
{
|
{
|
||||||
if (range.Count > 1)
|
if (range.Count > 1)
|
||||||
{
|
{
|
||||||
return GetBuffer(range, write).GetRange(range);
|
return GetBuffer(range, stage, write).GetRange(range);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MemoryRange subRange = range.GetSubRange(0);
|
MemoryRange subRange = range.GetSubRange(0);
|
||||||
return GetBuffer(subRange.Address, subRange.Size, write).GetRangeAligned(subRange.Address, subRange.Size, write);
|
return GetBuffer(subRange.Address, subRange.Size, stage, write).GetRangeAligned(subRange.Address, subRange.Size, write);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,18 +879,19 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// Gets a buffer sub-range for a given memory range.
|
/// Gets a buffer sub-range for a given memory range.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="range">Physical regions of memory where the buffer is mapped</param>
|
/// <param name="range">Physical regions of memory where the buffer is mapped</param>
|
||||||
|
/// <param name="stage">Buffer stage that triggered the access</param>
|
||||||
/// <param name="write">Whether the buffer will be written to by this use</param>
|
/// <param name="write">Whether the buffer will be written to by this use</param>
|
||||||
/// <returns>The buffer sub-range for the given range</returns>
|
/// <returns>The buffer sub-range for the given range</returns>
|
||||||
public BufferRange GetBufferRange(MultiRange range, bool write = false)
|
public BufferRange GetBufferRange(MultiRange range, BufferStage stage, bool write = false)
|
||||||
{
|
{
|
||||||
if (range.Count > 1)
|
if (range.Count > 1)
|
||||||
{
|
{
|
||||||
return GetBuffer(range, write).GetRange(range);
|
return GetBuffer(range, stage, write).GetRange(range);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MemoryRange subRange = range.GetSubRange(0);
|
MemoryRange subRange = range.GetSubRange(0);
|
||||||
return GetBuffer(subRange.Address, subRange.Size, write).GetRange(subRange.Address, subRange.Size, write);
|
return GetBuffer(subRange.Address, subRange.Size, stage, write).GetRange(subRange.Address, subRange.Size, write);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -888,9 +900,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// A buffer overlapping with the specified range is assumed to already exist on the cache.
|
/// A buffer overlapping with the specified range is assumed to already exist on the cache.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="range">Physical regions of memory where the buffer is mapped</param>
|
/// <param name="range">Physical regions of memory where the buffer is mapped</param>
|
||||||
|
/// <param name="stage">Buffer stage that triggered the access</param>
|
||||||
/// <param name="write">Whether the buffer will be written to by this use</param>
|
/// <param name="write">Whether the buffer will be written to by this use</param>
|
||||||
/// <returns>The buffer where the range is fully contained</returns>
|
/// <returns>The buffer where the range is fully contained</returns>
|
||||||
private MultiRangeBuffer GetBuffer(MultiRange range, bool write = false)
|
private MultiRangeBuffer GetBuffer(MultiRange range, BufferStage stage, bool write = false)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < range.Count; i++)
|
for (int i = 0; i < range.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -902,7 +915,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
if (write)
|
if (write)
|
||||||
{
|
{
|
||||||
subBuffer.SignalModified(subRange.Address, subRange.Size);
|
subBuffer.SignalModified(subRange.Address, subRange.Size, stage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -935,9 +948,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">Start address of the memory range</param>
|
/// <param name="address">Start address of the memory range</param>
|
||||||
/// <param name="size">Size in bytes of the memory range</param>
|
/// <param name="size">Size in bytes of the memory range</param>
|
||||||
|
/// <param name="stage">Buffer stage that triggered the access</param>
|
||||||
/// <param name="write">Whether the buffer will be written to by this use</param>
|
/// <param name="write">Whether the buffer will be written to by this use</param>
|
||||||
/// <returns>The buffer where the range is fully contained</returns>
|
/// <returns>The buffer where the range is fully contained</returns>
|
||||||
private Buffer GetBuffer(ulong address, ulong size, bool write = false)
|
private Buffer GetBuffer(ulong address, ulong size, BufferStage stage, bool write = false)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
|
|
||||||
@@ -950,7 +964,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
if (write)
|
if (write)
|
||||||
{
|
{
|
||||||
buffer.SignalModified(address, size);
|
buffer.SignalModified(address, size, stage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1004,6 +1018,18 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signal that the given buffer's handle has changed,
|
||||||
|
/// forcing rebind and any overlapping multi-range buffers to be recreated.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer that has changed handle</param>
|
||||||
|
public void BufferBackingChanged(Buffer buffer)
|
||||||
|
{
|
||||||
|
NotifyBuffersModified?.Invoke();
|
||||||
|
|
||||||
|
RecreateMultiRangeBuffers(buffer.Address, buffer.Size);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prune any invalid entries from a quick access dictionary.
|
/// Prune any invalid entries from a quick access dictionary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -156,7 +156,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="type">Type of each index buffer element</param>
|
/// <param name="type">Type of each index buffer element</param>
|
||||||
public void SetIndexBuffer(ulong gpuVa, ulong size, IndexType type)
|
public void SetIndexBuffer(ulong gpuVa, ulong size, IndexType type)
|
||||||
{
|
{
|
||||||
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size, BufferStage.IndexBuffer);
|
||||||
|
|
||||||
_indexBuffer.Range = range;
|
_indexBuffer.Range = range;
|
||||||
_indexBuffer.Type = type;
|
_indexBuffer.Type = type;
|
||||||
@@ -186,7 +186,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="divisor">Vertex divisor of the buffer, for instanced draws</param>
|
/// <param name="divisor">Vertex divisor of the buffer, for instanced draws</param>
|
||||||
public void SetVertexBuffer(int index, ulong gpuVa, ulong size, int stride, int divisor)
|
public void SetVertexBuffer(int index, ulong gpuVa, ulong size, int stride, int divisor)
|
||||||
{
|
{
|
||||||
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size, BufferStage.VertexBuffer);
|
||||||
|
|
||||||
_vertexBuffers[index].Range = range;
|
_vertexBuffers[index].Range = range;
|
||||||
_vertexBuffers[index].Stride = stride;
|
_vertexBuffers[index].Stride = stride;
|
||||||
@@ -213,7 +213,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="size">Size in bytes of the transform feedback buffer</param>
|
/// <param name="size">Size in bytes of the transform feedback buffer</param>
|
||||||
public void SetTransformFeedbackBuffer(int index, ulong gpuVa, ulong size)
|
public void SetTransformFeedbackBuffer(int index, ulong gpuVa, ulong size)
|
||||||
{
|
{
|
||||||
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size);
|
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size, BufferStage.TransformFeedback);
|
||||||
|
|
||||||
_transformFeedbackBuffers[index] = new BufferBounds(range);
|
_transformFeedbackBuffers[index] = new BufferBounds(range);
|
||||||
_transformFeedbackBuffersDirty = true;
|
_transformFeedbackBuffersDirty = true;
|
||||||
@@ -260,7 +260,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
gpuVa = BitUtils.AlignDown<ulong>(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
|
gpuVa = BitUtils.AlignDown<ulong>(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
|
||||||
|
|
||||||
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size);
|
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size, BufferStageUtils.ComputeStorage(flags));
|
||||||
|
|
||||||
_cpStorageBuffers.SetBounds(index, range, flags);
|
_cpStorageBuffers.SetBounds(index, range, flags);
|
||||||
}
|
}
|
||||||
@@ -284,7 +284,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
gpuVa = BitUtils.AlignDown<ulong>(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
|
gpuVa = BitUtils.AlignDown<ulong>(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
|
||||||
|
|
||||||
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size);
|
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size, BufferStageUtils.GraphicsStorage(stage, flags));
|
||||||
|
|
||||||
if (!buffers.Buffers[index].Range.Equals(range))
|
if (!buffers.Buffers[index].Range.Equals(range))
|
||||||
{
|
{
|
||||||
@@ -303,7 +303,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="size">Size in bytes of the storage buffer</param>
|
/// <param name="size">Size in bytes of the storage buffer</param>
|
||||||
public void SetComputeUniformBuffer(int index, ulong gpuVa, ulong size)
|
public void SetComputeUniformBuffer(int index, ulong gpuVa, ulong size)
|
||||||
{
|
{
|
||||||
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size, BufferStage.Compute);
|
||||||
|
|
||||||
_cpUniformBuffers.SetBounds(index, range);
|
_cpUniformBuffers.SetBounds(index, range);
|
||||||
}
|
}
|
||||||
@@ -318,7 +318,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="size">Size in bytes of the storage buffer</param>
|
/// <param name="size">Size in bytes of the storage buffer</param>
|
||||||
public void SetGraphicsUniformBuffer(int stage, int index, ulong gpuVa, ulong size)
|
public void SetGraphicsUniformBuffer(int stage, int index, ulong gpuVa, ulong size)
|
||||||
{
|
{
|
||||||
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size, BufferStageUtils.FromShaderStage(stage));
|
||||||
|
|
||||||
_gpUniformBuffers[stage].SetBounds(index, range);
|
_gpUniformBuffers[stage].SetBounds(index, range);
|
||||||
_gpUniformBuffersDirty = true;
|
_gpUniformBuffersDirty = true;
|
||||||
@@ -502,7 +502,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
foreach (var binding in _bufferTextures)
|
foreach (var binding in _bufferTextures)
|
||||||
{
|
{
|
||||||
var isStore = binding.BindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
|
var isStore = binding.BindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
|
||||||
var range = bufferCache.GetBufferRange(binding.Range, isStore);
|
var range = bufferCache.GetBufferRange(binding.Range, BufferStageUtils.TextureBuffer(binding.Stage, binding.BindingInfo.Flags), isStore);
|
||||||
binding.Texture.SetStorage(range);
|
binding.Texture.SetStorage(range);
|
||||||
|
|
||||||
// The texture must be rebound to use the new storage if it was updated.
|
// The texture must be rebound to use the new storage if it was updated.
|
||||||
@@ -526,7 +526,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
foreach (var binding in _bufferTextureArrays)
|
foreach (var binding in _bufferTextureArrays)
|
||||||
{
|
{
|
||||||
var range = bufferCache.GetBufferRange(binding.Range);
|
var range = bufferCache.GetBufferRange(binding.Range, BufferStage.None);
|
||||||
binding.Texture.SetStorage(range);
|
binding.Texture.SetStorage(range);
|
||||||
|
|
||||||
textureArray[0] = binding.Texture;
|
textureArray[0] = binding.Texture;
|
||||||
@@ -536,7 +536,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
foreach (var binding in _bufferImageArrays)
|
foreach (var binding in _bufferImageArrays)
|
||||||
{
|
{
|
||||||
var isStore = binding.BindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
|
var isStore = binding.BindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
|
||||||
var range = bufferCache.GetBufferRange(binding.Range, isStore);
|
var range = bufferCache.GetBufferRange(binding.Range, BufferStage.None, isStore);
|
||||||
binding.Texture.SetStorage(range);
|
binding.Texture.SetStorage(range);
|
||||||
|
|
||||||
textureArray[0] = binding.Texture;
|
textureArray[0] = binding.Texture;
|
||||||
@@ -565,7 +565,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
if (!_indexBuffer.Range.IsUnmapped)
|
if (!_indexBuffer.Range.IsUnmapped)
|
||||||
{
|
{
|
||||||
BufferRange buffer = bufferCache.GetBufferRange(_indexBuffer.Range);
|
BufferRange buffer = bufferCache.GetBufferRange(_indexBuffer.Range, BufferStage.IndexBuffer);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetIndexBuffer(buffer, _indexBuffer.Type);
|
_context.Renderer.Pipeline.SetIndexBuffer(buffer, _indexBuffer.Type);
|
||||||
}
|
}
|
||||||
@@ -597,7 +597,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferRange buffer = bufferCache.GetBufferRange(vb.Range);
|
BufferRange buffer = bufferCache.GetBufferRange(vb.Range, BufferStage.VertexBuffer);
|
||||||
|
|
||||||
vertexBuffers[index] = new VertexBufferDescriptor(buffer, vb.Stride, vb.Divisor);
|
vertexBuffers[index] = new VertexBufferDescriptor(buffer, vb.Stride, vb.Divisor);
|
||||||
}
|
}
|
||||||
@@ -637,7 +637,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
tfbs[index] = bufferCache.GetBufferRange(tfb.Range, write: true);
|
tfbs[index] = bufferCache.GetBufferRange(tfb.Range, BufferStage.TransformFeedback, write: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetTransformFeedbackBuffers(tfbs);
|
_context.Renderer.Pipeline.SetTransformFeedbackBuffers(tfbs);
|
||||||
@@ -684,7 +684,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
_context.SupportBufferUpdater.SetTfeOffset(index, tfeOffset);
|
_context.SupportBufferUpdater.SetTfeOffset(index, tfeOffset);
|
||||||
|
|
||||||
buffers[index] = new BufferAssignment(index, bufferCache.GetBufferRange(range, write: true));
|
buffers[index] = new BufferAssignment(index, bufferCache.GetBufferRange(range, BufferStage.TransformFeedback, write: true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -751,6 +751,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
for (ShaderStage stage = ShaderStage.Vertex; stage <= ShaderStage.Fragment; stage++)
|
for (ShaderStage stage = ShaderStage.Vertex; stage <= ShaderStage.Fragment; stage++)
|
||||||
{
|
{
|
||||||
ref var buffers = ref bindings[(int)stage - 1];
|
ref var buffers = ref bindings[(int)stage - 1];
|
||||||
|
BufferStage bufferStage = BufferStageUtils.FromShaderStage(stage);
|
||||||
|
|
||||||
for (int index = 0; index < buffers.Count; index++)
|
for (int index = 0; index < buffers.Count; index++)
|
||||||
{
|
{
|
||||||
@@ -762,8 +763,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
{
|
{
|
||||||
var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
|
var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
|
||||||
var range = isStorage
|
var range = isStorage
|
||||||
? bufferCache.GetBufferRangeAligned(bounds.Range, isWrite)
|
? bufferCache.GetBufferRangeAligned(bounds.Range, bufferStage | BufferStageUtils.FromUsage(bounds.Flags), isWrite)
|
||||||
: bufferCache.GetBufferRange(bounds.Range);
|
: bufferCache.GetBufferRange(bounds.Range, bufferStage);
|
||||||
|
|
||||||
ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range);
|
ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range);
|
||||||
}
|
}
|
||||||
@@ -799,8 +800,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
{
|
{
|
||||||
var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
|
var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
|
||||||
var range = isStorage
|
var range = isStorage
|
||||||
? bufferCache.GetBufferRangeAligned(bounds.Range, isWrite)
|
? bufferCache.GetBufferRangeAligned(bounds.Range, BufferStageUtils.ComputeStorage(bounds.Flags), isWrite)
|
||||||
: bufferCache.GetBufferRange(bounds.Range);
|
: bufferCache.GetBufferRange(bounds.Range, BufferStage.Compute);
|
||||||
|
|
||||||
ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range);
|
ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range);
|
||||||
}
|
}
|
||||||
@@ -875,7 +876,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
Format format,
|
Format format,
|
||||||
bool isImage)
|
bool isImage)
|
||||||
{
|
{
|
||||||
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(range);
|
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(range, BufferStageUtils.TextureBuffer(stage, bindingInfo.Flags));
|
||||||
|
|
||||||
_bufferTextures.Add(new BufferTextureBinding(stage, texture, range, bindingInfo, format, isImage));
|
_bufferTextures.Add(new BufferTextureBinding(stage, texture, range, bindingInfo, format, isImage));
|
||||||
}
|
}
|
||||||
@@ -883,6 +884,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the buffer storage of a buffer texture array element. This will be bound when the buffer manager commits bindings.
|
/// Sets the buffer storage of a buffer texture array element. This will be bound when the buffer manager commits bindings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="stage">Shader stage accessing the texture</param>
|
||||||
/// <param name="array">Texture array where the element will be inserted</param>
|
/// <param name="array">Texture array where the element will be inserted</param>
|
||||||
/// <param name="texture">Buffer texture</param>
|
/// <param name="texture">Buffer texture</param>
|
||||||
/// <param name="range">Physical ranges of memory where the buffer texture data is located</param>
|
/// <param name="range">Physical ranges of memory where the buffer texture data is located</param>
|
||||||
@@ -890,6 +892,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="index">Index of the binding on the array</param>
|
/// <param name="index">Index of the binding on the array</param>
|
||||||
/// <param name="format">Format of the buffer texture</param>
|
/// <param name="format">Format of the buffer texture</param>
|
||||||
public void SetBufferTextureStorage(
|
public void SetBufferTextureStorage(
|
||||||
|
ShaderStage stage,
|
||||||
ITextureArray array,
|
ITextureArray array,
|
||||||
ITexture texture,
|
ITexture texture,
|
||||||
MultiRange range,
|
MultiRange range,
|
||||||
@@ -897,7 +900,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
int index,
|
int index,
|
||||||
Format format)
|
Format format)
|
||||||
{
|
{
|
||||||
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(range);
|
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(range, BufferStageUtils.TextureBuffer(stage, bindingInfo.Flags));
|
||||||
|
|
||||||
_bufferTextureArrays.Add(new BufferTextureArrayBinding<ITextureArray>(array, texture, range, bindingInfo, index, format));
|
_bufferTextureArrays.Add(new BufferTextureArrayBinding<ITextureArray>(array, texture, range, bindingInfo, index, format));
|
||||||
}
|
}
|
||||||
@@ -905,6 +908,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the buffer storage of a buffer image array element. This will be bound when the buffer manager commits bindings.
|
/// Sets the buffer storage of a buffer image array element. This will be bound when the buffer manager commits bindings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="stage">Shader stage accessing the texture</param>
|
||||||
/// <param name="array">Image array where the element will be inserted</param>
|
/// <param name="array">Image array where the element will be inserted</param>
|
||||||
/// <param name="texture">Buffer texture</param>
|
/// <param name="texture">Buffer texture</param>
|
||||||
/// <param name="range">Physical ranges of memory where the buffer texture data is located</param>
|
/// <param name="range">Physical ranges of memory where the buffer texture data is located</param>
|
||||||
@@ -912,6 +916,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="index">Index of the binding on the array</param>
|
/// <param name="index">Index of the binding on the array</param>
|
||||||
/// <param name="format">Format of the buffer texture</param>
|
/// <param name="format">Format of the buffer texture</param>
|
||||||
public void SetBufferTextureStorage(
|
public void SetBufferTextureStorage(
|
||||||
|
ShaderStage stage,
|
||||||
IImageArray array,
|
IImageArray array,
|
||||||
ITexture texture,
|
ITexture texture,
|
||||||
MultiRange range,
|
MultiRange range,
|
||||||
@@ -919,7 +924,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
int index,
|
int index,
|
||||||
Format format)
|
Format format)
|
||||||
{
|
{
|
||||||
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(range);
|
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(range, BufferStageUtils.TextureBuffer(stage, bindingInfo.Flags));
|
||||||
|
|
||||||
_bufferImageArrays.Add(new BufferTextureArrayBinding<IImageArray>(array, texture, range, bindingInfo, index, format));
|
_bufferImageArrays.Add(new BufferTextureArrayBinding<IImageArray>(array, texture, range, bindingInfo, index, format));
|
||||||
}
|
}
|
||||||
|
@@ -1,37 +1,21 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Memory
|
namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A record of when buffer data was copied from one buffer to another, along with the SyncNumber when the migration will be complete.
|
/// A record of when buffer data was copied from multiple buffers to one migration target,
|
||||||
/// Keeps the source buffer alive for data flushes until the migration is complete.
|
/// along with the SyncNumber when the migration will be complete.
|
||||||
|
/// Keeps the source buffers alive for data flushes until the migration is complete.
|
||||||
|
/// All spans cover the full range of the "destination" buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class BufferMigration : IDisposable
|
internal class BufferMigration : IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The offset for the migrated region.
|
/// Ranges from source buffers that were copied as part of this migration.
|
||||||
|
/// Ordered by increasing base address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ulong _offset;
|
public BufferMigrationSpan[] Spans { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The size for the migrated region.
|
|
||||||
/// </summary>
|
|
||||||
private readonly ulong _size;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The buffer that was migrated from.
|
|
||||||
/// </summary>
|
|
||||||
private readonly Buffer _buffer;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The source range action, to be called on overlap with an unreached sync number.
|
|
||||||
/// </summary>
|
|
||||||
private readonly Action<ulong, ulong> _sourceRangeAction;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The source range list.
|
|
||||||
/// </summary>
|
|
||||||
private readonly BufferModifiedRangeList _source;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The destination range list. This range list must be updated when flushing the source.
|
/// The destination range list. This range list must be updated when flushing the source.
|
||||||
@@ -43,55 +27,193 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly ulong SyncNumber;
|
public readonly ulong SyncNumber;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of active users there are traversing this migration's spans.
|
||||||
|
/// </summary>
|
||||||
|
private int _refCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new buffer migration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="spans">Source spans for the migration</param>
|
||||||
|
/// <param name="destination">Destination buffer range list</param>
|
||||||
|
/// <param name="syncNumber">Sync number where this migration will be complete</param>
|
||||||
|
public BufferMigration(BufferMigrationSpan[] spans, BufferModifiedRangeList destination, ulong syncNumber)
|
||||||
|
{
|
||||||
|
Spans = spans;
|
||||||
|
Destination = destination;
|
||||||
|
SyncNumber = syncNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a span to the migration. Allocates a new array with the target size, and replaces it.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The base address for the span is assumed to be higher than all other spans in the migration,
|
||||||
|
/// to keep the span array ordered.
|
||||||
|
/// </remarks>
|
||||||
|
public void AddSpanToEnd(BufferMigrationSpan span)
|
||||||
|
{
|
||||||
|
BufferMigrationSpan[] oldSpans = Spans;
|
||||||
|
|
||||||
|
BufferMigrationSpan[] newSpans = new BufferMigrationSpan[oldSpans.Length + 1];
|
||||||
|
|
||||||
|
oldSpans.CopyTo(newSpans, 0);
|
||||||
|
|
||||||
|
newSpans[oldSpans.Length] = span;
|
||||||
|
|
||||||
|
Spans = newSpans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs the given range action, or one from a migration that overlaps and has not synced yet.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="offset">The offset to pass to the action</param>
|
||||||
|
/// <param name="size">The size to pass to the action</param>
|
||||||
|
/// <param name="syncNumber">The sync number that has been reached</param>
|
||||||
|
/// <param name="rangeAction">The action to perform</param>
|
||||||
|
public void RangeActionWithMigration(ulong offset, ulong size, ulong syncNumber, BufferFlushAction rangeAction)
|
||||||
|
{
|
||||||
|
long syncDiff = (long)(syncNumber - SyncNumber);
|
||||||
|
|
||||||
|
if (syncDiff >= 0)
|
||||||
|
{
|
||||||
|
// The migration has completed. Run the parent action.
|
||||||
|
rangeAction(offset, size, syncNumber);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _refCount);
|
||||||
|
|
||||||
|
ulong prevAddress = offset;
|
||||||
|
ulong endAddress = offset + size;
|
||||||
|
|
||||||
|
foreach (BufferMigrationSpan span in Spans)
|
||||||
|
{
|
||||||
|
if (!span.Overlaps(offset, size))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (span.Address > prevAddress)
|
||||||
|
{
|
||||||
|
// There's a gap between this span and the last (or the start address). Flush the range using the parent action.
|
||||||
|
|
||||||
|
rangeAction(prevAddress, span.Address - prevAddress, syncNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
span.RangeActionWithMigration(offset, size, syncNumber);
|
||||||
|
|
||||||
|
prevAddress = span.Address + span.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endAddress > prevAddress)
|
||||||
|
{
|
||||||
|
// There's a gap at the end of the range with no migration. Flush the range using the parent action.
|
||||||
|
rangeAction(prevAddress, endAddress - prevAddress, syncNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
Interlocked.Decrement(ref _refCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispose the buffer migration. This removes the reference from the destination range list,
|
||||||
|
/// and runs all the dispose buffers for the migration spans. (typically disposes the source buffer)
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
while (Volatile.Read(ref _refCount) > 0)
|
||||||
|
{
|
||||||
|
// Coming into this method, the sync for the migration will be met, so nothing can increment the ref count.
|
||||||
|
// However, an existing traversal of the spans for data flush could still be in progress.
|
||||||
|
// Spin if this is ever the case, so they don't get disposed before the operation is complete.
|
||||||
|
}
|
||||||
|
|
||||||
|
Destination.RemoveMigration(this);
|
||||||
|
|
||||||
|
foreach (BufferMigrationSpan span in Spans)
|
||||||
|
{
|
||||||
|
span.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A record of when buffer data was copied from one buffer to another, for a specific range in a source buffer.
|
||||||
|
/// Keeps the source buffer alive for data flushes until the migration is complete.
|
||||||
|
/// </summary>
|
||||||
|
internal readonly struct BufferMigrationSpan : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The offset for the migrated region.
|
||||||
|
/// </summary>
|
||||||
|
public readonly ulong Address;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size for the migrated region.
|
||||||
|
/// </summary>
|
||||||
|
public readonly ulong Size;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The action to perform when the migration isn't needed anymore.
|
||||||
|
/// </summary>
|
||||||
|
private readonly Action _disposeAction;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The source range action, to be called on overlap with an unreached sync number.
|
||||||
|
/// </summary>
|
||||||
|
private readonly BufferFlushAction _sourceRangeAction;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optional migration for the source data. Can chain together if many migrations happen in a short time.
|
||||||
|
/// If this is null, then _sourceRangeAction will always provide up to date data.
|
||||||
|
/// </summary>
|
||||||
|
private readonly BufferMigration _source;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a record for a buffer migration.
|
/// Creates a record for a buffer migration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="buffer">The source buffer for this migration</param>
|
/// <param name="buffer">The source buffer for this migration</param>
|
||||||
|
/// <param name="disposeAction">The action to perform when the migration isn't needed anymore</param>
|
||||||
/// <param name="sourceRangeAction">The flush action for the source buffer</param>
|
/// <param name="sourceRangeAction">The flush action for the source buffer</param>
|
||||||
/// <param name="source">The modified range list for the source buffer</param>
|
/// <param name="source">Pending migration for the source buffer</param>
|
||||||
/// <param name="dest">The modified range list for the destination buffer</param>
|
public BufferMigrationSpan(
|
||||||
/// <param name="syncNumber">The sync number for when the migration is complete</param>
|
|
||||||
public BufferMigration(
|
|
||||||
Buffer buffer,
|
Buffer buffer,
|
||||||
Action<ulong, ulong> sourceRangeAction,
|
Action disposeAction,
|
||||||
BufferModifiedRangeList source,
|
BufferFlushAction sourceRangeAction,
|
||||||
BufferModifiedRangeList dest,
|
BufferMigration source)
|
||||||
ulong syncNumber)
|
|
||||||
{
|
{
|
||||||
_offset = buffer.Address;
|
Address = buffer.Address;
|
||||||
_size = buffer.Size;
|
Size = buffer.Size;
|
||||||
_buffer = buffer;
|
_disposeAction = disposeAction;
|
||||||
_sourceRangeAction = sourceRangeAction;
|
_sourceRangeAction = sourceRangeAction;
|
||||||
_source = source;
|
_source = source;
|
||||||
Destination = dest;
|
|
||||||
SyncNumber = syncNumber;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a record for a buffer migration, using the default buffer dispose action.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The source buffer for this migration</param>
|
||||||
|
/// <param name="sourceRangeAction">The flush action for the source buffer</param>
|
||||||
|
/// <param name="source">Pending migration for the source buffer</param>
|
||||||
|
public BufferMigrationSpan(
|
||||||
|
Buffer buffer,
|
||||||
|
BufferFlushAction sourceRangeAction,
|
||||||
|
BufferMigration source) : this(buffer, buffer.DecrementReferenceCount, sourceRangeAction, source) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determine if the given range overlaps this migration, and has not been completed yet.
|
/// Determine if the given range overlaps this migration, and has not been completed yet.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="offset">Start offset</param>
|
/// <param name="offset">Start offset</param>
|
||||||
/// <param name="size">Range size</param>
|
/// <param name="size">Range size</param>
|
||||||
/// <param name="syncNumber">The sync number that was waited on</param>
|
|
||||||
/// <returns>True if overlapping and in progress, false otherwise</returns>
|
/// <returns>True if overlapping and in progress, false otherwise</returns>
|
||||||
public bool Overlaps(ulong offset, ulong size, ulong syncNumber)
|
public bool Overlaps(ulong offset, ulong size)
|
||||||
{
|
{
|
||||||
ulong end = offset + size;
|
ulong end = offset + size;
|
||||||
ulong destEnd = _offset + _size;
|
ulong destEnd = Address + Size;
|
||||||
long syncDiff = (long)(syncNumber - SyncNumber); // syncNumber is less if the copy has not completed.
|
|
||||||
|
|
||||||
return !(end <= _offset || offset >= destEnd) && syncDiff < 0;
|
return !(end <= Address || offset >= destEnd);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determine if the given range matches this migration.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="offset">Start offset</param>
|
|
||||||
/// <param name="size">Range size</param>
|
|
||||||
/// <returns>True if the range exactly matches, false otherwise</returns>
|
|
||||||
public bool FullyMatches(ulong offset, ulong size)
|
|
||||||
{
|
|
||||||
return _offset == offset && _size == size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -100,26 +222,30 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="offset">Start offset</param>
|
/// <param name="offset">Start offset</param>
|
||||||
/// <param name="size">Range size</param>
|
/// <param name="size">Range size</param>
|
||||||
/// <param name="syncNumber">Current sync number</param>
|
/// <param name="syncNumber">Current sync number</param>
|
||||||
/// <param name="parent">The modified range list that originally owned this range</param>
|
public void RangeActionWithMigration(ulong offset, ulong size, ulong syncNumber)
|
||||||
public void RangeActionWithMigration(ulong offset, ulong size, ulong syncNumber, BufferModifiedRangeList parent)
|
|
||||||
{
|
{
|
||||||
ulong end = offset + size;
|
ulong end = offset + size;
|
||||||
end = Math.Min(_offset + _size, end);
|
end = Math.Min(Address + Size, end);
|
||||||
offset = Math.Max(_offset, offset);
|
offset = Math.Max(Address, offset);
|
||||||
|
|
||||||
size = end - offset;
|
size = end - offset;
|
||||||
|
|
||||||
_source.RangeActionWithMigration(offset, size, syncNumber, parent, _sourceRangeAction);
|
if (_source != null)
|
||||||
|
{
|
||||||
|
_source.RangeActionWithMigration(offset, size, syncNumber, _sourceRangeAction);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_sourceRangeAction(offset, size, syncNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes this reference to the range list, potentially allowing for the source buffer to be disposed.
|
/// Removes this migration span, potentially allowing for the source buffer to be disposed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Destination.RemoveMigration(this);
|
_disposeAction();
|
||||||
|
|
||||||
_buffer.DecrementReferenceCount();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
using Ryujinx.Common.Pools;
|
using Ryujinx.Common.Pools;
|
||||||
using Ryujinx.Memory.Range;
|
using Ryujinx.Memory.Range;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Memory
|
namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
@@ -72,10 +71,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
private readonly GpuContext _context;
|
private readonly GpuContext _context;
|
||||||
private readonly Buffer _parent;
|
private readonly Buffer _parent;
|
||||||
private readonly Action<ulong, ulong> _flushAction;
|
private readonly BufferFlushAction _flushAction;
|
||||||
|
|
||||||
private List<BufferMigration> _sources;
|
private BufferMigration _source;
|
||||||
private BufferMigration _migrationTarget;
|
private BufferModifiedRangeList _migrationTarget;
|
||||||
|
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
|
|
||||||
@@ -99,7 +98,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="context">GPU context that the buffer range list belongs to</param>
|
/// <param name="context">GPU context that the buffer range list belongs to</param>
|
||||||
/// <param name="parent">The parent buffer that owns this range list</param>
|
/// <param name="parent">The parent buffer that owns this range list</param>
|
||||||
/// <param name="flushAction">The flush action for the parent buffer</param>
|
/// <param name="flushAction">The flush action for the parent buffer</param>
|
||||||
public BufferModifiedRangeList(GpuContext context, Buffer parent, Action<ulong, ulong> flushAction) : base(BackingInitialSize)
|
public BufferModifiedRangeList(GpuContext context, Buffer parent, BufferFlushAction flushAction) : base(BackingInitialSize)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
@@ -199,6 +198,36 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets modified ranges within the specified region, and then fires the given action for each range individually.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Start address to query</param>
|
||||||
|
/// <param name="size">Size to query</param>
|
||||||
|
/// <param name="syncNumber">Sync number required for a range to be signalled</param>
|
||||||
|
/// <param name="rangeAction">The action to call for each modified range</param>
|
||||||
|
public void GetRangesAtSync(ulong address, ulong size, ulong syncNumber, Action<ulong, ulong> rangeAction)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
ref var overlaps = ref ThreadStaticArray<BufferModifiedRange>.Get();
|
||||||
|
|
||||||
|
// Range list must be consistent for this operation.
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
count = FindOverlapsNonOverlapping(address, size, ref overlaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
BufferModifiedRange overlap = overlaps[i];
|
||||||
|
|
||||||
|
if (overlap.SyncNumber == syncNumber)
|
||||||
|
{
|
||||||
|
rangeAction(overlap.Address, overlap.Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets modified ranges within the specified region, and then fires the given action for each range individually.
|
/// Gets modified ranges within the specified region, and then fires the given action for each range individually.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -245,41 +274,16 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <param name="offset">The offset to pass to the action</param>
|
/// <param name="offset">The offset to pass to the action</param>
|
||||||
/// <param name="size">The size to pass to the action</param>
|
/// <param name="size">The size to pass to the action</param>
|
||||||
/// <param name="syncNumber">The sync number that has been reached</param>
|
/// <param name="syncNumber">The sync number that has been reached</param>
|
||||||
/// <param name="parent">The modified range list that originally owned this range</param>
|
|
||||||
/// <param name="rangeAction">The action to perform</param>
|
/// <param name="rangeAction">The action to perform</param>
|
||||||
public void RangeActionWithMigration(ulong offset, ulong size, ulong syncNumber, BufferModifiedRangeList parent, Action<ulong, ulong> rangeAction)
|
public void RangeActionWithMigration(ulong offset, ulong size, ulong syncNumber, BufferFlushAction rangeAction)
|
||||||
{
|
{
|
||||||
bool firstSource = true;
|
if (_source != null)
|
||||||
|
|
||||||
if (parent != this)
|
|
||||||
{
|
{
|
||||||
lock (_lock)
|
_source.RangeActionWithMigration(offset, size, syncNumber, rangeAction);
|
||||||
{
|
|
||||||
if (_sources != null)
|
|
||||||
{
|
|
||||||
foreach (BufferMigration source in _sources)
|
|
||||||
{
|
|
||||||
if (source.Overlaps(offset, size, syncNumber))
|
|
||||||
{
|
|
||||||
if (firstSource && !source.FullyMatches(offset, size))
|
|
||||||
{
|
|
||||||
// Perform this buffer's action first. The migrations will run after.
|
|
||||||
rangeAction(offset, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
source.RangeActionWithMigration(offset, size, syncNumber, parent);
|
|
||||||
|
|
||||||
firstSource = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (firstSource)
|
|
||||||
{
|
{
|
||||||
// No overlapping migrations, or they are not meant for this range, flush the data using the given action.
|
rangeAction(offset, size, syncNumber);
|
||||||
rangeAction(offset, size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +323,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
ClearPart(overlap, clampAddress, clampEnd);
|
ClearPart(overlap, clampAddress, clampEnd);
|
||||||
|
|
||||||
RangeActionWithMigration(clampAddress, clampEnd - clampAddress, waitSync, overlap.Parent, _flushAction);
|
RangeActionWithMigration(clampAddress, clampEnd - clampAddress, waitSync, _flushAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +333,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
// There is a migration target to call instead. This can't be changed after set so accessing it outside the lock is fine.
|
// There is a migration target to call instead. This can't be changed after set so accessing it outside the lock is fine.
|
||||||
|
|
||||||
_migrationTarget.Destination.RemoveRangesAndFlush(overlaps, rangeCount, highestDiff, currentSync, address, endAddress);
|
_migrationTarget.RemoveRangesAndFlush(overlaps, rangeCount, highestDiff, currentSync, address, endAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -367,7 +371,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
if (rangeCount == -1)
|
if (rangeCount == -1)
|
||||||
{
|
{
|
||||||
_migrationTarget.Destination.WaitForAndFlushRanges(address, size);
|
_migrationTarget.WaitForAndFlushRanges(address, size);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -407,6 +411,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inherit ranges from another modified range list.
|
/// Inherit ranges from another modified range list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Assumes that ranges will be inherited in address ascending order.
|
||||||
|
/// </remarks>
|
||||||
/// <param name="ranges">The range list to inherit from</param>
|
/// <param name="ranges">The range list to inherit from</param>
|
||||||
/// <param name="registerRangeAction">The action to call for each modified range</param>
|
/// <param name="registerRangeAction">The action to call for each modified range</param>
|
||||||
public void InheritRanges(BufferModifiedRangeList ranges, Action<ulong, ulong> registerRangeAction)
|
public void InheritRanges(BufferModifiedRangeList ranges, Action<ulong, ulong> registerRangeAction)
|
||||||
@@ -415,18 +422,31 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
|
|
||||||
lock (ranges._lock)
|
lock (ranges._lock)
|
||||||
{
|
{
|
||||||
BufferMigration migration = new(ranges._parent, ranges._flushAction, ranges, this, _context.SyncNumber);
|
|
||||||
|
|
||||||
ranges._parent.IncrementReferenceCount();
|
|
||||||
ranges._migrationTarget = migration;
|
|
||||||
|
|
||||||
_context.RegisterBufferMigration(migration);
|
|
||||||
|
|
||||||
inheritRanges = ranges.ToArray();
|
inheritRanges = ranges.ToArray();
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
(_sources ??= new List<BufferMigration>()).Add(migration);
|
// Copy over the migration from the previous range list
|
||||||
|
|
||||||
|
BufferMigration oldMigration = ranges._source;
|
||||||
|
|
||||||
|
BufferMigrationSpan span = new BufferMigrationSpan(ranges._parent, ranges._flushAction, oldMigration);
|
||||||
|
ranges._parent.IncrementReferenceCount();
|
||||||
|
|
||||||
|
if (_source == null)
|
||||||
|
{
|
||||||
|
// Create a new migration.
|
||||||
|
_source = new BufferMigration(new BufferMigrationSpan[] { span }, this, _context.SyncNumber);
|
||||||
|
|
||||||
|
_context.RegisterBufferMigration(_source);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Extend the migration
|
||||||
|
_source.AddSpanToEnd(span);
|
||||||
|
}
|
||||||
|
|
||||||
|
ranges._migrationTarget = this;
|
||||||
|
|
||||||
foreach (BufferModifiedRange range in inheritRanges)
|
foreach (BufferModifiedRange range in inheritRanges)
|
||||||
{
|
{
|
||||||
@@ -445,6 +465,27 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Register a migration from previous buffer storage. This migration is from a snapshot of the buffer's
|
||||||
|
/// current handle to its handle in the future, and is assumed to be complete when the sync action completes.
|
||||||
|
/// When the migration completes, the handle is disposed.
|
||||||
|
/// </summary>
|
||||||
|
public void SelfMigration()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
BufferMigrationSpan span = new(_parent, _parent.GetSnapshotDisposeAction(), _parent.GetSnapshotFlushAction(), _source);
|
||||||
|
BufferMigration migration = new(new BufferMigrationSpan[] { span }, this, _context.SyncNumber);
|
||||||
|
|
||||||
|
// Migration target is used to redirect flush actions to the latest range list,
|
||||||
|
// so we don't need to set it here. (this range list is still the latest)
|
||||||
|
|
||||||
|
_context.RegisterBufferMigration(migration);
|
||||||
|
|
||||||
|
_source = migration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a source buffer migration, indicating its copy has completed.
|
/// Removes a source buffer migration, indicating its copy has completed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -453,7 +494,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
_sources.Remove(migration);
|
if (_source == migration)
|
||||||
|
{
|
||||||
|
_source = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
295
ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferPreFlush.cs
Normal file
295
ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferPreFlush.cs
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Manages flushing ranges from buffers in advance for easy access, if they are flushed often.
|
||||||
|
/// Typically, from device local memory to a host mapped target for cached access.
|
||||||
|
/// </summary>
|
||||||
|
internal class BufferPreFlush : IDisposable
|
||||||
|
{
|
||||||
|
private const ulong PageSize = MemoryManager.PageSize;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Threshold for the number of copies without a flush required to disable preflush on a page.
|
||||||
|
/// </summary>
|
||||||
|
private const int DeactivateCopyThreshold = 200;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Value that indicates whether a page has been flushed or copied before.
|
||||||
|
/// </summary>
|
||||||
|
private enum PreFlushState
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
HasFlushed,
|
||||||
|
HasCopied
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flush state for each page of the buffer.
|
||||||
|
/// Controls whether data should be copied to the flush buffer, what sync is expected
|
||||||
|
/// and unflushed copy counting for stopping copies that are no longer needed.
|
||||||
|
/// </summary>
|
||||||
|
private struct PreFlushPage
|
||||||
|
{
|
||||||
|
public PreFlushState State;
|
||||||
|
public ulong FirstActivatedSync;
|
||||||
|
public ulong LastCopiedSync;
|
||||||
|
public int CopyCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if there are ranges that should copy to the flush buffer, false otherwise.
|
||||||
|
/// </summary>
|
||||||
|
public bool ShouldCopy { get; private set; }
|
||||||
|
|
||||||
|
private readonly GpuContext _context;
|
||||||
|
private readonly Buffer _buffer;
|
||||||
|
private readonly PreFlushPage[] _pages;
|
||||||
|
private readonly ulong _address;
|
||||||
|
private readonly ulong _size;
|
||||||
|
private readonly ulong _misalignment;
|
||||||
|
private readonly Action<BufferHandle, ulong, ulong> _flushAction;
|
||||||
|
|
||||||
|
private BufferHandle _flushBuffer;
|
||||||
|
|
||||||
|
public BufferPreFlush(GpuContext context, Buffer parent, Action<BufferHandle, ulong, ulong> flushAction)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_buffer = parent;
|
||||||
|
_address = parent.Address;
|
||||||
|
_size = parent.Size;
|
||||||
|
_pages = new PreFlushPage[BitUtils.DivRoundUp(_size, PageSize)];
|
||||||
|
_misalignment = _address & (PageSize - 1);
|
||||||
|
|
||||||
|
_flushAction = flushAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensure that the flush buffer exists.
|
||||||
|
/// </summary>
|
||||||
|
private void EnsureFlushBuffer()
|
||||||
|
{
|
||||||
|
if (_flushBuffer == BufferHandle.Null)
|
||||||
|
{
|
||||||
|
_flushBuffer = _context.Renderer.CreateBuffer((int)_size, BufferAccess.HostMemory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a page range from an address and size byte range.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Range address</param>
|
||||||
|
/// <param name="size">Range size</param>
|
||||||
|
/// <returns>A page index and count</returns>
|
||||||
|
private (int index, int count) GetPageRange(ulong address, ulong size)
|
||||||
|
{
|
||||||
|
ulong offset = address - _address;
|
||||||
|
ulong endOffset = offset + size;
|
||||||
|
|
||||||
|
int basePage = (int)(offset / PageSize);
|
||||||
|
int endPage = (int)((endOffset - 1) / PageSize);
|
||||||
|
|
||||||
|
return (basePage, 1 + endPage - basePage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an offset and size range in the parent buffer from a page index and count.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startPage">Range start page</param>
|
||||||
|
/// <param name="count">Range page count</param>
|
||||||
|
/// <returns>Offset and size range</returns>
|
||||||
|
private (int offset, int size) GetOffset(int startPage, int count)
|
||||||
|
{
|
||||||
|
int offset = (int)((ulong)startPage * PageSize - _misalignment);
|
||||||
|
int endOffset = (int)((ulong)(startPage + count) * PageSize - _misalignment);
|
||||||
|
|
||||||
|
offset = Math.Max(0, offset);
|
||||||
|
endOffset = Math.Min((int)_size, endOffset);
|
||||||
|
|
||||||
|
return (offset, endOffset - offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copy a range of pages from the parent buffer into the flush buffer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startPage">Range start page</param>
|
||||||
|
/// <param name="count">Range page count</param>
|
||||||
|
private void CopyPageRange(int startPage, int count)
|
||||||
|
{
|
||||||
|
(int offset, int size) = GetOffset(startPage, count);
|
||||||
|
|
||||||
|
EnsureFlushBuffer();
|
||||||
|
|
||||||
|
_context.Renderer.Pipeline.CopyBuffer(_buffer.Handle, _flushBuffer, offset, offset, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copy a modified range into the flush buffer if it's marked as flushed.
|
||||||
|
/// Any pages the range overlaps are copied, and copies aren't repeated in the same sync number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Range address</param>
|
||||||
|
/// <param name="size">Range size</param>
|
||||||
|
public void CopyModified(ulong address, ulong size)
|
||||||
|
{
|
||||||
|
(int baseIndex, int count) = GetPageRange(address, size);
|
||||||
|
ulong syncNumber = _context.SyncNumber;
|
||||||
|
|
||||||
|
int startPage = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
int pageIndex = baseIndex + i;
|
||||||
|
ref PreFlushPage page = ref _pages[pageIndex];
|
||||||
|
|
||||||
|
if (page.State > PreFlushState.None)
|
||||||
|
{
|
||||||
|
// Perform the copy, and update the state of each page.
|
||||||
|
if (startPage == -1)
|
||||||
|
{
|
||||||
|
startPage = pageIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page.State != PreFlushState.HasCopied)
|
||||||
|
{
|
||||||
|
page.FirstActivatedSync = syncNumber;
|
||||||
|
page.State = PreFlushState.HasCopied;
|
||||||
|
}
|
||||||
|
else if (page.CopyCount++ >= DeactivateCopyThreshold)
|
||||||
|
{
|
||||||
|
page.CopyCount = 0;
|
||||||
|
page.State = PreFlushState.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page.LastCopiedSync != syncNumber)
|
||||||
|
{
|
||||||
|
page.LastCopiedSync = syncNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (startPage != -1)
|
||||||
|
{
|
||||||
|
CopyPageRange(startPage, pageIndex - startPage);
|
||||||
|
|
||||||
|
startPage = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startPage != -1)
|
||||||
|
{
|
||||||
|
CopyPageRange(startPage, (baseIndex + count) - startPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flush the given page range back into guest memory, optionally using data from the flush buffer.
|
||||||
|
/// The actual flushed range is an intersection of the page range and the address range.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Address range start</param>
|
||||||
|
/// <param name="size">Address range size</param>
|
||||||
|
/// <param name="startPage">Page range start</param>
|
||||||
|
/// <param name="count">Page range count</param>
|
||||||
|
/// <param name="preFlush">True if the data should come from the flush buffer</param>
|
||||||
|
private void FlushPageRange(ulong address, ulong size, int startPage, int count, bool preFlush)
|
||||||
|
{
|
||||||
|
(int pageOffset, int pageSize) = GetOffset(startPage, count);
|
||||||
|
|
||||||
|
int offset = (int)(address - _address);
|
||||||
|
int end = offset + (int)size;
|
||||||
|
|
||||||
|
offset = Math.Max(offset, pageOffset);
|
||||||
|
end = Math.Min(end, pageOffset + pageSize);
|
||||||
|
|
||||||
|
if (end >= offset)
|
||||||
|
{
|
||||||
|
BufferHandle handle = preFlush ? _flushBuffer : _buffer.Handle;
|
||||||
|
_flushAction(handle, _address + (ulong)offset, (ulong)(end - offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flush the given address range back into guest memory, optionally using data from the flush buffer.
|
||||||
|
/// When a copy has been performed on or before the waited sync number, the data can come from the flush buffer.
|
||||||
|
/// Otherwise, it flushes the parent buffer directly.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">Range address</param>
|
||||||
|
/// <param name="size">Range size</param>
|
||||||
|
/// <param name="syncNumber">Sync number that has been waited for</param>
|
||||||
|
public void FlushWithAction(ulong address, ulong size, ulong syncNumber)
|
||||||
|
{
|
||||||
|
// Copy the parts of the range that have pre-flush copies that have been completed.
|
||||||
|
// Run the flush action for ranges that don't have pre-flush copies.
|
||||||
|
|
||||||
|
// If a range doesn't have a pre-flush copy, consider adding one.
|
||||||
|
|
||||||
|
(int baseIndex, int count) = GetPageRange(address, size);
|
||||||
|
|
||||||
|
bool rangePreFlushed = false;
|
||||||
|
int startPage = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
int pageIndex = baseIndex + i;
|
||||||
|
ref PreFlushPage page = ref _pages[pageIndex];
|
||||||
|
|
||||||
|
bool flushPage = false;
|
||||||
|
page.CopyCount = 0;
|
||||||
|
|
||||||
|
if (page.State == PreFlushState.HasCopied)
|
||||||
|
{
|
||||||
|
if (syncNumber >= page.FirstActivatedSync)
|
||||||
|
{
|
||||||
|
// After the range is first activated, its data will always be copied to the preflush buffer on each sync.
|
||||||
|
flushPage = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (page.State == PreFlushState.None)
|
||||||
|
{
|
||||||
|
page.State = PreFlushState.HasFlushed;
|
||||||
|
ShouldCopy = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flushPage)
|
||||||
|
{
|
||||||
|
if (!rangePreFlushed || startPage == -1)
|
||||||
|
{
|
||||||
|
if (startPage != -1)
|
||||||
|
{
|
||||||
|
FlushPageRange(address, size, startPage, pageIndex - startPage, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
rangePreFlushed = true;
|
||||||
|
startPage = pageIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rangePreFlushed || startPage == -1)
|
||||||
|
{
|
||||||
|
if (startPage != -1)
|
||||||
|
{
|
||||||
|
FlushPageRange(address, size, startPage, pageIndex - startPage, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
rangePreFlushed = false;
|
||||||
|
startPage = pageIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startPage != -1)
|
||||||
|
{
|
||||||
|
FlushPageRange(address, size, startPage, (baseIndex + count) - startPage, rangePreFlushed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispose the flush buffer, if present.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_flushBuffer != BufferHandle.Null)
|
||||||
|
{
|
||||||
|
_context.Renderer.DeleteBuffer(_flushBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs
Normal file
99
ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
using Ryujinx.Graphics.Shader;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Pipeline stages that can modify buffer data, as well as flags indicating storage usage.
|
||||||
|
/// Must match ShaderStage for the shader stages, though anything after that can be in any order.
|
||||||
|
/// </summary>
|
||||||
|
internal enum BufferStage : byte
|
||||||
|
{
|
||||||
|
Compute,
|
||||||
|
Vertex,
|
||||||
|
TessellationControl,
|
||||||
|
TessellationEvaluation,
|
||||||
|
Geometry,
|
||||||
|
Fragment,
|
||||||
|
|
||||||
|
Indirect,
|
||||||
|
VertexBuffer,
|
||||||
|
IndexBuffer,
|
||||||
|
Copy,
|
||||||
|
TransformFeedback,
|
||||||
|
Internal,
|
||||||
|
None,
|
||||||
|
|
||||||
|
StageMask = 0x3f,
|
||||||
|
StorageMask = 0xc0,
|
||||||
|
|
||||||
|
StorageRead = 0x40,
|
||||||
|
StorageWrite = 0x80,
|
||||||
|
|
||||||
|
#pragma warning disable CA1069 // Enums values should not be duplicated
|
||||||
|
StorageAtomic = 0xc0
|
||||||
|
#pragma warning restore CA1069 // Enums values should not be duplicated
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Utility methods to convert shader stages and binding flags into buffer stages.
|
||||||
|
/// </summary>
|
||||||
|
internal static class BufferStageUtils
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static BufferStage FromShaderStage(ShaderStage stage)
|
||||||
|
{
|
||||||
|
return (BufferStage)stage;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static BufferStage FromShaderStage(int stageIndex)
|
||||||
|
{
|
||||||
|
return (BufferStage)(stageIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static BufferStage FromUsage(BufferUsageFlags flags)
|
||||||
|
{
|
||||||
|
if (flags.HasFlag(BufferUsageFlags.Write))
|
||||||
|
{
|
||||||
|
return BufferStage.StorageWrite;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return BufferStage.StorageRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static BufferStage FromUsage(TextureUsageFlags flags)
|
||||||
|
{
|
||||||
|
if (flags.HasFlag(TextureUsageFlags.ImageStore))
|
||||||
|
{
|
||||||
|
return BufferStage.StorageWrite;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return BufferStage.StorageRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static BufferStage TextureBuffer(ShaderStage shaderStage, TextureUsageFlags flags)
|
||||||
|
{
|
||||||
|
return FromShaderStage(shaderStage) | FromUsage(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static BufferStage GraphicsStorage(int stageIndex, BufferUsageFlags flags)
|
||||||
|
{
|
||||||
|
return FromShaderStage(stageIndex) | FromUsage(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static BufferStage ComputeStorage(BufferUsageFlags flags)
|
||||||
|
{
|
||||||
|
return BufferStage.Compute | FromUsage(flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -61,7 +61,9 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
BufferCount++;
|
BufferCount++;
|
||||||
|
|
||||||
if (access.HasFlag(GAL.BufferAccess.FlushPersistent))
|
var memType = access & GAL.BufferAccess.MemoryTypeMask;
|
||||||
|
|
||||||
|
if (memType == GAL.BufferAccess.HostMemory)
|
||||||
{
|
{
|
||||||
BufferHandle handle = Buffer.CreatePersistent(size);
|
BufferHandle handle = Buffer.CreatePersistent(size);
|
||||||
|
|
||||||
@@ -75,11 +77,6 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferHandle CreateBuffer(int size, GAL.BufferAccess access, BufferHandle storageHint)
|
|
||||||
{
|
|
||||||
return CreateBuffer(size, access);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BufferHandle CreateBuffer(nint pointer, int size)
|
public BufferHandle CreateBuffer(nint pointer, int size)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
@@ -148,6 +145,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
return new Capabilities(
|
return new Capabilities(
|
||||||
api: TargetApi.OpenGL,
|
api: TargetApi.OpenGL,
|
||||||
vendorName: GpuVendor,
|
vendorName: GpuVendor,
|
||||||
|
memoryType: SystemMemoryType.BackendManaged,
|
||||||
hasFrontFacingBug: intelWindows,
|
hasFrontFacingBug: intelWindows,
|
||||||
hasVectorIndexingBug: amdWindows,
|
hasVectorIndexingBug: amdWindows,
|
||||||
needsFragmentOutputSpecialization: false,
|
needsFragmentOutputSpecialization: false,
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
using Ryujinx.Common.Logging;
|
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
@@ -31,40 +30,29 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private readonly VulkanRenderer _gd;
|
private readonly VulkanRenderer _gd;
|
||||||
private readonly Device _device;
|
private readonly Device _device;
|
||||||
private MemoryAllocation _allocation;
|
private readonly MemoryAllocation _allocation;
|
||||||
private Auto<DisposableBuffer> _buffer;
|
private readonly Auto<DisposableBuffer> _buffer;
|
||||||
private Auto<MemoryAllocation> _allocationAuto;
|
private readonly Auto<MemoryAllocation> _allocationAuto;
|
||||||
private readonly bool _allocationImported;
|
private readonly bool _allocationImported;
|
||||||
private ulong _bufferHandle;
|
private readonly ulong _bufferHandle;
|
||||||
|
|
||||||
private CacheByRange<BufferHolder> _cachedConvertedBuffers;
|
private CacheByRange<BufferHolder> _cachedConvertedBuffers;
|
||||||
|
|
||||||
public int Size { get; }
|
public int Size { get; }
|
||||||
|
|
||||||
private IntPtr _map;
|
private readonly IntPtr _map;
|
||||||
|
|
||||||
private MultiFenceHolder _waitable;
|
private readonly MultiFenceHolder _waitable;
|
||||||
|
|
||||||
private bool _lastAccessIsWrite;
|
private bool _lastAccessIsWrite;
|
||||||
|
|
||||||
private BufferAllocationType _baseType;
|
private readonly BufferAllocationType _baseType;
|
||||||
private BufferAllocationType _currentType;
|
private readonly BufferAllocationType _activeType;
|
||||||
private bool _swapQueued;
|
|
||||||
|
|
||||||
public BufferAllocationType DesiredType { get; private set; }
|
|
||||||
|
|
||||||
private int _setCount;
|
|
||||||
private int _writeCount;
|
|
||||||
private int _flushCount;
|
|
||||||
private int _flushTemp;
|
|
||||||
private int _lastFlushWrite = -1;
|
|
||||||
|
|
||||||
private readonly ReaderWriterLockSlim _flushLock;
|
private readonly ReaderWriterLockSlim _flushLock;
|
||||||
private FenceHolder _flushFence;
|
private FenceHolder _flushFence;
|
||||||
private int _flushWaiting;
|
private int _flushWaiting;
|
||||||
|
|
||||||
private List<Action> _swapActions;
|
|
||||||
|
|
||||||
private byte[] _pendingData;
|
private byte[] _pendingData;
|
||||||
private BufferMirrorRangeList _pendingDataRanges;
|
private BufferMirrorRangeList _pendingDataRanges;
|
||||||
private Dictionary<ulong, StagingBufferReserved> _mirrors;
|
private Dictionary<ulong, StagingBufferReserved> _mirrors;
|
||||||
@@ -83,8 +71,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_map = allocation.HostPointer;
|
_map = allocation.HostPointer;
|
||||||
|
|
||||||
_baseType = type;
|
_baseType = type;
|
||||||
_currentType = currentType;
|
_activeType = currentType;
|
||||||
DesiredType = currentType;
|
|
||||||
|
|
||||||
_flushLock = new ReaderWriterLockSlim();
|
_flushLock = new ReaderWriterLockSlim();
|
||||||
_useMirrors = gd.IsTBDR;
|
_useMirrors = gd.IsTBDR;
|
||||||
@@ -104,8 +91,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_map = _allocation.HostPointer + offset;
|
_map = _allocation.HostPointer + offset;
|
||||||
|
|
||||||
_baseType = type;
|
_baseType = type;
|
||||||
_currentType = currentType;
|
_activeType = currentType;
|
||||||
DesiredType = currentType;
|
|
||||||
|
|
||||||
_flushLock = new ReaderWriterLockSlim();
|
_flushLock = new ReaderWriterLockSlim();
|
||||||
}
|
}
|
||||||
@@ -120,164 +106,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Size = size;
|
Size = size;
|
||||||
|
|
||||||
_baseType = BufferAllocationType.Sparse;
|
_baseType = BufferAllocationType.Sparse;
|
||||||
_currentType = BufferAllocationType.Sparse;
|
_activeType = BufferAllocationType.Sparse;
|
||||||
DesiredType = BufferAllocationType.Sparse;
|
|
||||||
|
|
||||||
_flushLock = new ReaderWriterLockSlim();
|
_flushLock = new ReaderWriterLockSlim();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryBackingSwap(ref CommandBufferScoped? cbs)
|
|
||||||
{
|
|
||||||
if (_swapQueued && DesiredType != _currentType)
|
|
||||||
{
|
|
||||||
// Only swap if the buffer is not used in any queued command buffer.
|
|
||||||
bool isRented = _buffer.HasRentedCommandBufferDependency(_gd.CommandBufferPool);
|
|
||||||
|
|
||||||
if (!isRented && _gd.CommandBufferPool.OwnedByCurrentThread && !_flushLock.IsReadLockHeld && (_pendingData == null || cbs != null))
|
|
||||||
{
|
|
||||||
var currentAllocation = _allocationAuto;
|
|
||||||
var currentBuffer = _buffer;
|
|
||||||
IntPtr currentMap = _map;
|
|
||||||
|
|
||||||
(VkBuffer buffer, MemoryAllocation allocation, BufferAllocationType resultType) = _gd.BufferManager.CreateBacking(_gd, Size, DesiredType, false, false, _currentType);
|
|
||||||
|
|
||||||
if (buffer.Handle != 0)
|
|
||||||
{
|
|
||||||
if (cbs != null)
|
|
||||||
{
|
|
||||||
ClearMirrors(cbs.Value, 0, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
_flushLock.EnterWriteLock();
|
|
||||||
|
|
||||||
ClearFlushFence();
|
|
||||||
|
|
||||||
_waitable = new MultiFenceHolder(Size);
|
|
||||||
|
|
||||||
_allocation = allocation;
|
|
||||||
_allocationAuto = new Auto<MemoryAllocation>(allocation);
|
|
||||||
_buffer = new Auto<DisposableBuffer>(new DisposableBuffer(_gd.Api, _device, buffer), this, _waitable, _allocationAuto);
|
|
||||||
_bufferHandle = buffer.Handle;
|
|
||||||
_map = allocation.HostPointer;
|
|
||||||
|
|
||||||
if (_map != IntPtr.Zero && currentMap != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
// Copy data directly. Readbacks don't have to wait if this is done.
|
|
||||||
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
new Span<byte>((void*)currentMap, Size).CopyTo(new Span<byte>((void*)_map, Size));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cbs ??= _gd.CommandBufferPool.Rent();
|
|
||||||
|
|
||||||
CommandBufferScoped cbsV = cbs.Value;
|
|
||||||
|
|
||||||
Copy(_gd, cbsV, currentBuffer, _buffer, 0, 0, Size);
|
|
||||||
|
|
||||||
// Need to wait for the data to reach the new buffer before data can be flushed.
|
|
||||||
|
|
||||||
_flushFence = _gd.CommandBufferPool.GetFence(cbsV.CommandBufferIndex);
|
|
||||||
_flushFence.Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Debug?.PrintMsg(LogClass.Gpu, $"Converted {Size} buffer {_currentType} to {resultType}");
|
|
||||||
|
|
||||||
_currentType = resultType;
|
|
||||||
|
|
||||||
if (_swapActions != null)
|
|
||||||
{
|
|
||||||
foreach (var action in _swapActions)
|
|
||||||
{
|
|
||||||
action();
|
|
||||||
}
|
|
||||||
|
|
||||||
_swapActions.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
currentBuffer.Dispose();
|
|
||||||
currentAllocation.Dispose();
|
|
||||||
|
|
||||||
_gd.PipelineInternal.SwapBuffer(currentBuffer, _buffer);
|
|
||||||
|
|
||||||
_flushLock.ExitWriteLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
_swapQueued = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_swapQueued = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConsiderBackingSwap()
|
|
||||||
{
|
|
||||||
if (_baseType == BufferAllocationType.Auto)
|
|
||||||
{
|
|
||||||
// When flushed, wait for a bit more info to make a decision.
|
|
||||||
bool wasFlushed = _flushTemp > 0;
|
|
||||||
int multiplier = wasFlushed ? 2 : 0;
|
|
||||||
if (_writeCount >= (WriteCountThreshold << multiplier) || _setCount >= (SetCountThreshold << multiplier) || _flushCount >= (FlushCountThreshold << multiplier))
|
|
||||||
{
|
|
||||||
if (_flushCount > 0 || _flushTemp-- > 0)
|
|
||||||
{
|
|
||||||
// Buffers that flush should ideally be mapped in host address space for easy copies.
|
|
||||||
// If the buffer is large it will do better on GPU memory, as there will be more writes than data flushes (typically individual pages).
|
|
||||||
// If it is small, then it's likely most of the buffer will be flushed so we want it on host memory, as access is cached.
|
|
||||||
|
|
||||||
bool hostMappingSensitive = _gd.Vendor == Vendor.Nvidia;
|
|
||||||
bool deviceLocalMapped = Size > DeviceLocalSizeThreshold || (wasFlushed && _writeCount > _flushCount * 10 && hostMappingSensitive) || _currentType == BufferAllocationType.DeviceLocalMapped;
|
|
||||||
|
|
||||||
DesiredType = deviceLocalMapped ? BufferAllocationType.DeviceLocalMapped : BufferAllocationType.HostMapped;
|
|
||||||
|
|
||||||
// It's harder for a buffer that is flushed to revert to another type of mapping.
|
|
||||||
if (_flushCount > 0)
|
|
||||||
{
|
|
||||||
_flushTemp = 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (_writeCount >= (WriteCountThreshold << multiplier))
|
|
||||||
{
|
|
||||||
// Buffers that are written often should ideally be in the device local heap. (Storage buffers)
|
|
||||||
DesiredType = BufferAllocationType.DeviceLocal;
|
|
||||||
}
|
|
||||||
else if (_setCount > (SetCountThreshold << multiplier))
|
|
||||||
{
|
|
||||||
// Buffers that have their data set often should ideally be host mapped. (Constant buffers)
|
|
||||||
DesiredType = BufferAllocationType.HostMapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastFlushWrite = -1;
|
|
||||||
_flushCount = 0;
|
|
||||||
_writeCount = 0;
|
|
||||||
_setCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_swapQueued && DesiredType != _currentType)
|
|
||||||
{
|
|
||||||
_swapQueued = true;
|
|
||||||
|
|
||||||
_gd.PipelineInternal.AddBackingSwap(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Pin()
|
|
||||||
{
|
|
||||||
if (_baseType == BufferAllocationType.Auto)
|
|
||||||
{
|
|
||||||
_baseType = _currentType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe Auto<DisposableBufferView> CreateView(VkFormat format, int offset, int size, Action invalidateView)
|
public unsafe Auto<DisposableBufferView> CreateView(VkFormat format, int offset, int size, Action invalidateView)
|
||||||
{
|
{
|
||||||
var bufferViewCreateInfo = new BufferViewCreateInfo
|
var bufferViewCreateInfo = new BufferViewCreateInfo
|
||||||
@@ -291,19 +124,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
_gd.Api.CreateBufferView(_device, bufferViewCreateInfo, null, out var bufferView).ThrowOnError();
|
_gd.Api.CreateBufferView(_device, bufferViewCreateInfo, null, out var bufferView).ThrowOnError();
|
||||||
|
|
||||||
(_swapActions ??= new List<Action>()).Add(invalidateView);
|
|
||||||
|
|
||||||
return new Auto<DisposableBufferView>(new DisposableBufferView(_gd.Api, _device, bufferView), this, _waitable, _buffer);
|
return new Auto<DisposableBufferView>(new DisposableBufferView(_gd.Api, _device, bufferView), this, _waitable, _buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InheritMetrics(BufferHolder other)
|
|
||||||
{
|
|
||||||
_setCount = other._setCount;
|
|
||||||
_writeCount = other._writeCount;
|
|
||||||
_flushCount = other._flushCount;
|
|
||||||
_flushTemp = other._flushTemp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe void InsertBarrier(CommandBuffer commandBuffer, bool isWrite)
|
public unsafe void InsertBarrier(CommandBuffer commandBuffer, bool isWrite)
|
||||||
{
|
{
|
||||||
// If the last access is write, we always need a barrier to be sure we will read or modify
|
// If the last access is write, we always need a barrier to be sure we will read or modify
|
||||||
@@ -423,18 +246,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
if (isWrite)
|
if (isWrite)
|
||||||
{
|
{
|
||||||
_writeCount++;
|
|
||||||
|
|
||||||
SignalWrite(0, Size);
|
SignalWrite(0, Size);
|
||||||
}
|
}
|
||||||
else if (isSSBO)
|
|
||||||
{
|
|
||||||
// Always consider SSBO access for swapping to device local memory.
|
|
||||||
|
|
||||||
_writeCount++;
|
|
||||||
|
|
||||||
ConsiderBackingSwap();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _buffer;
|
return _buffer;
|
||||||
}
|
}
|
||||||
@@ -443,8 +256,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
if (isWrite)
|
if (isWrite)
|
||||||
{
|
{
|
||||||
_writeCount++;
|
|
||||||
|
|
||||||
SignalWrite(offset, size);
|
SignalWrite(offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,8 +354,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void SignalWrite(int offset, int size)
|
public void SignalWrite(int offset, int size)
|
||||||
{
|
{
|
||||||
ConsiderBackingSwap();
|
|
||||||
|
|
||||||
if (offset == 0 && size == Size)
|
if (offset == 0 && size == Size)
|
||||||
{
|
{
|
||||||
_cachedConvertedBuffers.Clear();
|
_cachedConvertedBuffers.Clear();
|
||||||
@@ -624,13 +433,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
WaitForFlushFence();
|
WaitForFlushFence();
|
||||||
|
|
||||||
if (_lastFlushWrite != _writeCount)
|
|
||||||
{
|
|
||||||
// If it's on the same page as the last flush, ignore it.
|
|
||||||
_lastFlushWrite = _writeCount;
|
|
||||||
_flushCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Span<byte> result;
|
Span<byte> result;
|
||||||
|
|
||||||
if (_map != IntPtr.Zero)
|
if (_map != IntPtr.Zero)
|
||||||
@@ -711,8 +513,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_setCount++;
|
bool allowMirror = _useMirrors && allowCbsWait && cbs != null && _activeType <= BufferAllocationType.HostMapped;
|
||||||
bool allowMirror = _useMirrors && allowCbsWait && cbs != null && _currentType <= BufferAllocationType.HostMapped;
|
|
||||||
|
|
||||||
if (_map != IntPtr.Zero)
|
if (_map != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
@@ -863,8 +664,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
var dstBuffer = GetBuffer(cbs.CommandBuffer, dstOffset, data.Length, true).Get(cbs, dstOffset, data.Length, true).Value;
|
var dstBuffer = GetBuffer(cbs.CommandBuffer, dstOffset, data.Length, true).Get(cbs, dstOffset, data.Length, true).Value;
|
||||||
|
|
||||||
_writeCount--;
|
|
||||||
|
|
||||||
InsertBufferBarrier(
|
InsertBufferBarrier(
|
||||||
_gd,
|
_gd,
|
||||||
cbs.CommandBuffer,
|
cbs.CommandBuffer,
|
||||||
@@ -1100,8 +899,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_swapQueued = false;
|
|
||||||
|
|
||||||
_gd.PipelineInternal?.FlushCommandsIfWeightExceeding(_buffer, (ulong)Size);
|
_gd.PipelineInternal?.FlushCommandsIfWeightExceeding(_buffer, (ulong)Size);
|
||||||
|
|
||||||
_buffer.Dispose();
|
_buffer.Dispose();
|
||||||
|
@@ -165,10 +165,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (TryGetBuffer(range.Handle, out var existingHolder))
|
if (TryGetBuffer(range.Handle, out var existingHolder))
|
||||||
{
|
{
|
||||||
// Since this buffer now also owns the memory from the referenced buffer,
|
|
||||||
// we pin it to ensure the memory location will not change.
|
|
||||||
existingHolder.Pin();
|
|
||||||
|
|
||||||
(var memory, var offset) = existingHolder.GetDeviceMemoryAndOffset();
|
(var memory, var offset) = existingHolder.GetDeviceMemoryAndOffset();
|
||||||
|
|
||||||
memoryBinds[index] = new SparseMemoryBind()
|
memoryBinds[index] = new SparseMemoryBind()
|
||||||
@@ -235,10 +231,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
int size,
|
int size,
|
||||||
bool sparseCompatible = false,
|
bool sparseCompatible = false,
|
||||||
BufferAllocationType baseType = BufferAllocationType.HostMapped,
|
BufferAllocationType baseType = BufferAllocationType.HostMapped,
|
||||||
BufferHandle storageHint = default,
|
|
||||||
bool forceMirrors = false)
|
bool forceMirrors = false)
|
||||||
{
|
{
|
||||||
return CreateWithHandle(gd, size, out _, sparseCompatible, baseType, storageHint, forceMirrors);
|
return CreateWithHandle(gd, size, out _, sparseCompatible, baseType, forceMirrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferHandle CreateWithHandle(
|
public BufferHandle CreateWithHandle(
|
||||||
@@ -247,10 +242,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
out BufferHolder holder,
|
out BufferHolder holder,
|
||||||
bool sparseCompatible = false,
|
bool sparseCompatible = false,
|
||||||
BufferAllocationType baseType = BufferAllocationType.HostMapped,
|
BufferAllocationType baseType = BufferAllocationType.HostMapped,
|
||||||
BufferHandle storageHint = default,
|
|
||||||
bool forceMirrors = false)
|
bool forceMirrors = false)
|
||||||
{
|
{
|
||||||
holder = Create(gd, size, forConditionalRendering: false, sparseCompatible, baseType, storageHint);
|
holder = Create(gd, size, forConditionalRendering: false, sparseCompatible, baseType);
|
||||||
if (holder == null)
|
if (holder == null)
|
||||||
{
|
{
|
||||||
return BufferHandle.Null;
|
return BufferHandle.Null;
|
||||||
@@ -387,31 +381,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
int size,
|
int size,
|
||||||
bool forConditionalRendering = false,
|
bool forConditionalRendering = false,
|
||||||
bool sparseCompatible = false,
|
bool sparseCompatible = false,
|
||||||
BufferAllocationType baseType = BufferAllocationType.HostMapped,
|
BufferAllocationType baseType = BufferAllocationType.HostMapped)
|
||||||
BufferHandle storageHint = default)
|
|
||||||
{
|
{
|
||||||
BufferAllocationType type = baseType;
|
BufferAllocationType type = baseType;
|
||||||
BufferHolder storageHintHolder = null;
|
|
||||||
|
|
||||||
if (baseType == BufferAllocationType.Auto)
|
if (baseType == BufferAllocationType.Auto)
|
||||||
{
|
{
|
||||||
if (gd.IsSharedMemory)
|
type = BufferAllocationType.HostMapped;
|
||||||
{
|
|
||||||
baseType = BufferAllocationType.HostMapped;
|
|
||||||
type = baseType;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
type = size >= BufferHolder.DeviceLocalSizeThreshold ? BufferAllocationType.DeviceLocal : BufferAllocationType.HostMapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (storageHint != BufferHandle.Null)
|
|
||||||
{
|
|
||||||
if (TryGetBuffer(storageHint, out storageHintHolder))
|
|
||||||
{
|
|
||||||
type = storageHintHolder.DesiredType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(VkBuffer buffer, MemoryAllocation allocation, BufferAllocationType resultType) =
|
(VkBuffer buffer, MemoryAllocation allocation, BufferAllocationType resultType) =
|
||||||
@@ -421,11 +397,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
var holder = new BufferHolder(gd, _device, buffer, allocation, size, baseType, resultType);
|
var holder = new BufferHolder(gd, _device, buffer, allocation, size, baseType, resultType);
|
||||||
|
|
||||||
if (storageHintHolder != null)
|
|
||||||
{
|
|
||||||
holder.InheritMetrics(storageHintHolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
return holder;
|
return holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -424,10 +424,20 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public static BufferAllocationType Convert(this BufferAccess access)
|
public static BufferAllocationType Convert(this BufferAccess access)
|
||||||
{
|
{
|
||||||
if (access.HasFlag(BufferAccess.FlushPersistent) || access.HasFlag(BufferAccess.Stream))
|
BufferAccess memType = access & BufferAccess.MemoryTypeMask;
|
||||||
|
|
||||||
|
if (memType == BufferAccess.HostMemory || access.HasFlag(BufferAccess.Stream))
|
||||||
{
|
{
|
||||||
return BufferAllocationType.HostMapped;
|
return BufferAllocationType.HostMapped;
|
||||||
}
|
}
|
||||||
|
else if (memType == BufferAccess.DeviceMemory)
|
||||||
|
{
|
||||||
|
return BufferAllocationType.DeviceLocal;
|
||||||
|
}
|
||||||
|
else if (memType == BufferAccess.DeviceMemoryMapped)
|
||||||
|
{
|
||||||
|
return BufferAllocationType.DeviceLocalMapped;
|
||||||
|
}
|
||||||
|
|
||||||
return BufferAllocationType.Auto;
|
return BufferAllocationType.Auto;
|
||||||
}
|
}
|
||||||
|
@@ -222,20 +222,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryBackingSwaps()
|
|
||||||
{
|
|
||||||
CommandBufferScoped? cbs = null;
|
|
||||||
|
|
||||||
_backingSwaps.RemoveAll(holder => holder.TryBackingSwap(ref cbs));
|
|
||||||
|
|
||||||
cbs?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddBackingSwap(BufferHolder holder)
|
|
||||||
{
|
|
||||||
_backingSwaps.Add(holder);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Restore()
|
public void Restore()
|
||||||
{
|
{
|
||||||
if (Pipeline != null)
|
if (Pipeline != null)
|
||||||
@@ -291,8 +277,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
Gd.ResetCounterPool();
|
Gd.ResetCounterPool();
|
||||||
|
|
||||||
TryBackingSwaps();
|
|
||||||
|
|
||||||
Restore();
|
Restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -486,12 +486,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public BufferHandle CreateBuffer(int size, BufferAccess access)
|
public BufferHandle CreateBuffer(int size, BufferAccess access)
|
||||||
{
|
{
|
||||||
return BufferManager.CreateWithHandle(this, size, access.HasFlag(BufferAccess.SparseCompatible), access.Convert(), default, access == BufferAccess.Stream);
|
return BufferManager.CreateWithHandle(this, size, access.HasFlag(BufferAccess.SparseCompatible), access.Convert(), access.HasFlag(BufferAccess.Stream));
|
||||||
}
|
|
||||||
|
|
||||||
public BufferHandle CreateBuffer(int size, BufferAccess access, BufferHandle storageHint)
|
|
||||||
{
|
|
||||||
return BufferManager.CreateWithHandle(this, size, access.HasFlag(BufferAccess.SparseCompatible), access.Convert(), storageHint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferHandle CreateBuffer(nint pointer, int size)
|
public BufferHandle CreateBuffer(nint pointer, int size)
|
||||||
@@ -675,9 +670,23 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
var limits = _physicalDevice.PhysicalDeviceProperties.Limits;
|
var limits = _physicalDevice.PhysicalDeviceProperties.Limits;
|
||||||
var mainQueueProperties = _physicalDevice.QueueFamilyProperties[QueueFamilyIndex];
|
var mainQueueProperties = _physicalDevice.QueueFamilyProperties[QueueFamilyIndex];
|
||||||
|
|
||||||
|
SystemMemoryType memoryType;
|
||||||
|
|
||||||
|
if (IsSharedMemory)
|
||||||
|
{
|
||||||
|
memoryType = SystemMemoryType.UnifiedMemory;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memoryType = Vendor == Vendor.Nvidia ?
|
||||||
|
SystemMemoryType.DedicatedMemorySlowStorage :
|
||||||
|
SystemMemoryType.DedicatedMemory;
|
||||||
|
}
|
||||||
|
|
||||||
return new Capabilities(
|
return new Capabilities(
|
||||||
api: TargetApi.Vulkan,
|
api: TargetApi.Vulkan,
|
||||||
GpuVendor,
|
GpuVendor,
|
||||||
|
memoryType: memoryType,
|
||||||
hasFrontFacingBug: IsIntelWindows,
|
hasFrontFacingBug: IsIntelWindows,
|
||||||
hasVectorIndexingBug: Vendor == Vendor.Qualcomm,
|
hasVectorIndexingBug: Vendor == Vendor.Qualcomm,
|
||||||
needsFragmentOutputSpecialization: IsMoltenVk,
|
needsFragmentOutputSpecialization: IsMoltenVk,
|
||||||
|
28
shadowsocks-rust/Cargo.lock
generated
28
shadowsocks-rust/Cargo.lock
generated
@@ -1716,9 +1716,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libmimalloc-sys"
|
name = "libmimalloc-sys"
|
||||||
version = "0.1.37"
|
version = "0.1.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "81eb4061c0582dedea1cbc7aff2240300dd6982e0239d1c99e65c1dbf4a30ba7"
|
checksum = "0e7bb23d733dfcc8af652a78b7bf232f0e967710d044732185e561e47c0336b6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1853,9 +1853,9 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mimalloc"
|
name = "mimalloc"
|
||||||
version = "0.1.41"
|
version = "0.1.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f41a2280ded0da56c8cf898babb86e8f10651a34adcfff190ae9a1159c6908d"
|
checksum = "e9186d86b79b52f4a77af65604b51225e8db1d6ee7e3f41aec1e40829c71a176"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libmimalloc-sys",
|
"libmimalloc-sys",
|
||||||
]
|
]
|
||||||
@@ -2377,9 +2377,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prost"
|
name = "prost"
|
||||||
version = "0.12.4"
|
version = "0.12.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922"
|
checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"prost-derive",
|
"prost-derive",
|
||||||
@@ -2408,9 +2408,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prost-derive"
|
name = "prost-derive"
|
||||||
version = "0.12.5"
|
version = "0.12.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9554e3ab233f0a932403704f1a1d08c30d5ccd931adfdfa1e8b5a19b52c1d55a"
|
checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"itertools",
|
"itertools",
|
||||||
@@ -3419,9 +3419,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sysexits"
|
name = "sysexits"
|
||||||
version = "0.7.13"
|
version = "0.7.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62e933b3bce3eff11227656c623ffff3fd4de6d5410c3fc68de49ecca26bc2be"
|
checksum = "b5b86c78a4dc8f92a6c34c96eea37290389c40fe3ffe8a4dd9898cf8a1f14282"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-configuration"
|
name = "system-configuration"
|
||||||
@@ -3483,18 +3483,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.60"
|
version = "1.0.61"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
|
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.60"
|
version = "1.0.61"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
|
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@@ -134,7 +134,7 @@ byte_string = "1.0"
|
|||||||
byteorder = "1.5"
|
byteorder = "1.5"
|
||||||
rand = { version = "0.8", features = ["small_rng"] }
|
rand = { version = "0.8", features = ["small_rng"] }
|
||||||
sled = { version = "0.34.7", features = ["compression"], optional = true }
|
sled = { version = "0.34.7", features = ["compression"], optional = true }
|
||||||
prost = { version = "0.12.4", optional = true }
|
prost = { version = "0.12.6", optional = true }
|
||||||
|
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
tokio = { version = "1.5", features = [
|
tokio = { version = "1.5", features = [
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
#### 1.9.0-rc.19
|
#### 1.9.0-rc.20
|
||||||
|
|
||||||
* Fixes and improvements
|
* Prioritize `*_route_address` in linux auto-route
|
||||||
|
* Fix `*_route_address` in darwin auto-route
|
||||||
|
|
||||||
#### 1.8.14
|
#### 1.8.14
|
||||||
|
|
||||||
|
@@ -33,7 +33,7 @@ require (
|
|||||||
github.com/sagernet/sing-shadowsocks v0.2.6
|
github.com/sagernet/sing-shadowsocks v0.2.6
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4
|
github.com/sagernet/sing-shadowtls v0.1.4
|
||||||
github.com/sagernet/sing-tun v0.3.0-beta.2
|
github.com/sagernet/sing-tun v0.3.0-beta.5
|
||||||
github.com/sagernet/sing-vmess v0.1.8
|
github.com/sagernet/sing-vmess v0.1.8
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
||||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6
|
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6
|
||||||
|
@@ -120,8 +120,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wK
|
|||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||||
github.com/sagernet/sing-tun v0.3.0-beta.2 h1:sfeHWnBTKGpFUjXpT+O/JEwFP8oVAo3M0Xx94ghesjU=
|
github.com/sagernet/sing-tun v0.3.0-beta.5 h1:z+4l1mGjPeepxT3mzHzE2pms995iUac/AyKQvRnWbWA=
|
||||||
github.com/sagernet/sing-tun v0.3.0-beta.2/go.mod h1:xPaOkQhngPMILx+/9DMLCFl4vSxUU2tMnCPSlf05HLo=
|
github.com/sagernet/sing-tun v0.3.0-beta.5/go.mod h1:xPaOkQhngPMILx+/9DMLCFl4vSxUU2tMnCPSlf05HLo=
|
||||||
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
|
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
|
||||||
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
|
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||||
|
@@ -155,22 +155,22 @@ msgid "Obfuscation Password"
|
|||||||
msgstr "混淆密码"
|
msgstr "混淆密码"
|
||||||
|
|
||||||
msgid "Hysterir QUIC parameters"
|
msgid "Hysterir QUIC parameters"
|
||||||
msgstr "QUIC参数"
|
msgstr "QUIC 参数"
|
||||||
|
|
||||||
msgid "QUIC initStreamReceiveWindow"
|
msgid "QUIC initStreamReceiveWindow"
|
||||||
msgstr "QUIC初始流接收窗口大小。"
|
msgstr "QUIC 初始流接收窗口大小。"
|
||||||
|
|
||||||
msgid "QUIC maxStreamReceiveWindow"
|
msgid "QUIC maxStreamReceiveWindow"
|
||||||
msgstr "QUIC最大的流接收窗口大小"
|
msgstr "QUIC 最大的流接收窗口大小"
|
||||||
|
|
||||||
msgid "QUIC initConnReceiveWindow"
|
msgid "QUIC initConnReceiveWindow"
|
||||||
msgstr "QUIC初始的连接接收窗口大小"
|
msgstr "QUIC 初始的连接接收窗口大小"
|
||||||
|
|
||||||
msgid "QUIC maxConnReceiveWindow"
|
msgid "QUIC maxConnReceiveWindow"
|
||||||
msgstr "QUIC最大的连接接收窗口大小"
|
msgstr "QUIC 最大的连接接收窗口大小"
|
||||||
|
|
||||||
msgid "QUIC maxIdleTimeout(Unit:second)"
|
msgid "QUIC maxIdleTimeout(Unit:second)"
|
||||||
msgstr "QUIC最长空闲超时时间(单位:秒)"
|
msgstr "QUIC 最长空闲超时时间(单位:秒)"
|
||||||
|
|
||||||
msgid "The keep-alive period.(Unit:second)"
|
msgid "The keep-alive period.(Unit:second)"
|
||||||
msgstr "心跳包发送间隔(单位:秒)"
|
msgstr "心跳包发送间隔(单位:秒)"
|
||||||
@@ -195,7 +195,7 @@ msgid "Shadow-TLS ChainPoxy type"
|
|||||||
msgstr "代理链类型"
|
msgstr "代理链类型"
|
||||||
|
|
||||||
msgid "Shadowsocks-rust Version"
|
msgid "Shadowsocks-rust Version"
|
||||||
msgstr "shadowsocks rust版本"
|
msgstr "shadowsocks rust 版本"
|
||||||
|
|
||||||
msgid "Vmess Protocol"
|
msgid "Vmess Protocol"
|
||||||
msgstr "VMESS协议"
|
msgstr "VMESS协议"
|
||||||
@@ -1003,19 +1003,19 @@ msgid "Enable Netflix Mode"
|
|||||||
msgstr "启用 Netflix 分流模式"
|
msgstr "启用 Netflix 分流模式"
|
||||||
|
|
||||||
msgid "TUIC User UUID"
|
msgid "TUIC User UUID"
|
||||||
msgstr "TUIC用户uuid"
|
msgstr "TUIC 用户 uuid"
|
||||||
|
|
||||||
msgid "TUIC Server IP Address"
|
msgid "TUIC Server IP Address"
|
||||||
msgstr "TUIC 服务器IP地址"
|
msgstr "TUIC 服务器 IP 地址"
|
||||||
|
|
||||||
msgid "TUIC User Password"
|
msgid "TUIC User Password"
|
||||||
msgstr "TUIC用户密钥"
|
msgstr "TUIC 用户密钥"
|
||||||
|
|
||||||
msgid "UDP relay mode"
|
msgid "UDP relay mode"
|
||||||
msgstr "UDP中继模式"
|
msgstr "UDP 中继模式"
|
||||||
|
|
||||||
msgid "native UDP characteristics"
|
msgid "native UDP characteristics"
|
||||||
msgstr "原生UDP特性"
|
msgstr "原生 UDP 特性"
|
||||||
|
|
||||||
msgid "lossless UDP relay using QUIC streams"
|
msgid "lossless UDP relay using QUIC streams"
|
||||||
msgstr "使用 QUIC 流的无损 UDP 中继"
|
msgstr "使用 QUIC 流的无损 UDP 中继"
|
||||||
@@ -1030,13 +1030,13 @@ msgid "Timeout for establishing a connection to server(second)"
|
|||||||
msgstr "连接超时时间(单位:秒)"
|
msgstr "连接超时时间(单位:秒)"
|
||||||
|
|
||||||
msgid "Garbage collection interval(second)"
|
msgid "Garbage collection interval(second)"
|
||||||
msgstr "UDP数据包片残片清理间隔(单位:秒)"
|
msgstr "UDP 数据包片残片清理间隔(单位:秒)"
|
||||||
|
|
||||||
msgid "Garbage collection lifetime(second)"
|
msgid "Garbage collection lifetime(second)"
|
||||||
msgstr "UDP数据包残片在服务器的保留时间(单位:秒)"
|
msgstr "UDP 数据包残片在服务器的保留时间(单位:秒)"
|
||||||
|
|
||||||
msgid "Disable SNI"
|
msgid "Disable SNI"
|
||||||
msgstr "关闭SNI服务器名称指示"
|
msgstr "关闭 SNI 服务器名称指示"
|
||||||
|
|
||||||
msgid "Enable 0-RTT QUIC handshake"
|
msgid "Enable 0-RTT QUIC handshake"
|
||||||
msgstr "客户端启用 0-RTT QUIC 连接握手"
|
msgstr "客户端启用 0-RTT QUIC 连接握手"
|
||||||
@@ -1048,13 +1048,13 @@ msgid "TUIC receive window"
|
|||||||
msgstr "接收窗口(无需确认即可接收的最大字节数:默认8Mb)"
|
msgstr "接收窗口(无需确认即可接收的最大字节数:默认8Mb)"
|
||||||
|
|
||||||
msgid "Dual-stack Listening Socket"
|
msgid "Dual-stack Listening Socket"
|
||||||
msgstr "双栈Socket监听"
|
msgstr "双栈 Socket 监听"
|
||||||
|
|
||||||
msgid "If this option is not set, the socket behavior is platform dependent."
|
msgid "If this option is not set, the socket behavior is platform dependent."
|
||||||
msgstr "如果未设置此选项,则套接字行为依赖于平台。"
|
msgstr "如果未设置此选项,则 Socket 行为依赖于平台。"
|
||||||
|
|
||||||
msgid "Maximum packet size the socks5 server can receive from external"
|
msgid "Maximum packet size the socks5 server can receive from external"
|
||||||
msgstr "socks5服务器可以从外部接收的最大数据包大小(单位:字节)"
|
msgstr "socks5 服务器可以从外部接收的最大数据包大小(单位:字节)"
|
||||||
|
|
||||||
msgid "Disable ChinaDNS-NG"
|
msgid "Disable ChinaDNS-NG"
|
||||||
msgstr "直通模式(禁用ChinaDNS-NG)"
|
msgstr "直通模式(禁用 ChinaDNS-NG)"
|
||||||
|
@@ -6,12 +6,12 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=sing-box
|
PKG_NAME:=sing-box
|
||||||
PKG_VERSION:=1.8.13
|
PKG_VERSION:=1.8.14
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://codeload.github.com/SagerNet/sing-box/tar.gz/v$(PKG_VERSION)?
|
PKG_SOURCE_URL:=https://codeload.github.com/SagerNet/sing-box/tar.gz/v$(PKG_VERSION)?
|
||||||
PKG_HASH:=de1c09d096c6fca9f59863a051438aeb3197713faa6518cb46d7ca0a9bc63976
|
PKG_HASH:=2ba7cfa097f5963ba304d47606e7a6b61bf881eb86cbed78fa6e4efae44a0a5f
|
||||||
|
|
||||||
PKG_LICENSE:=GPL-3.0-or-later
|
PKG_LICENSE:=GPL-3.0-or-later
|
||||||
PKG_LICENSE_FILES:=LICENSE
|
PKG_LICENSE_FILES:=LICENSE
|
||||||
|
@@ -30,13 +30,13 @@ define Download/geosite
|
|||||||
HASH:=25d6120b009498ac83ae723e9751a19ff545fac4800dad53ab6e2592c3407533
|
HASH:=25d6120b009498ac83ae723e9751a19ff545fac4800dad53ab6e2592c3407533
|
||||||
endef
|
endef
|
||||||
|
|
||||||
GEOSITE_IRAN_VER:=202405130027
|
GEOSITE_IRAN_VER:=202405200027
|
||||||
GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER)
|
GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER)
|
||||||
define Download/geosite-ir
|
define Download/geosite-ir
|
||||||
URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/
|
URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/
|
||||||
URL_FILE:=iran.dat
|
URL_FILE:=iran.dat
|
||||||
FILE:=$(GEOSITE_IRAN_FILE)
|
FILE:=$(GEOSITE_IRAN_FILE)
|
||||||
HASH:=a20aace2fb0e7a2a90bf8b18f7ce01478244f545a419ebc515f94f129bcd2085
|
HASH:=19b8a3aa46f5ce3543f9e3ebe64ad3437ce02189ba67be4d7931d7babdf42a84
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/v2ray-geodata/template
|
define Package/v2ray-geodata/template
|
||||||
|
@@ -6,5 +6,5 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||||||
|
|
||||||
Please check out the
|
Please check out the
|
||||||
|
|
||||||
* [Contributors's guide](https://gitlab.com/suyu-emu/suyu/-/wikis/Contributing).
|
* [Contributors's guide](https://git.suyu.dev/suyu/suyu/wiki/Contributing).
|
||||||
* [Merge request guidelines](https://gitlab.com/suyu-emu/suyu/-/wikis/Merge-requests)
|
* [Merge request guidelines](https://git.suyu.dev/suyu/suyu/wiki/Typical-Git-Workflow#once-your-pull-request-is-ready-to-be-merged)
|
||||||
|
21
suyu/MIGRATION.md
Normal file
21
suyu/MIGRATION.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Migrating from yuzu
|
||||||
|
|
||||||
|
When coming from yuzu, the migration is as easy as renaming some directories.
|
||||||
|
|
||||||
|
## Windows
|
||||||
|
|
||||||
|
Use the run dialog to go to `%APPDATA%` or manually go to `C:\Users\{USERNAME}\AppData\Roaming` (you may have to enable hidden files) and simply rename the `yuzu` directories and simply rename those to `suyu`.
|
||||||
|
|
||||||
|
## Unix (macOS/Linux)
|
||||||
|
Similarly, you can simply rename the folders `~/.local/share/yuzu` and `~/.config/yuzu` to `suyu`, either via a file manager or with the following commands:
|
||||||
|
```sh
|
||||||
|
$ mv ~/.local/share/yuzu ~/.local/share/suyu
|
||||||
|
$ mv ~/.config/yuzu ~/.config/suyu
|
||||||
|
```
|
||||||
|
There is also `~/.cache/yuzu`, which you can safely delete. Suyu will build a fresh cache in its own directory.
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
Depending on your setup, you may want to substitute those base paths for `$XDG_DATA_HOME` and `$XDG_CONFIG_HOME` respectively.
|
||||||
|
|
||||||
|
## Android
|
||||||
|
TBD
|
@@ -9,7 +9,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
We're in need of developers. Please join our chat below if you want to contribute!
|
We're in need of developers. Please join our chat below if you want to contribute!
|
||||||
This repo was based on Yuzu EA 4176 but the code is being rewritten from the ground up for legal and performance reasons.
|
This repo was based on Yuzu EA 4176 but the code is being rewritten from the ground up for legal and performance reasons.
|
||||||
|
|
||||||
Support the original suyu developer team [here](https://discord.gg/ajz5hdrZ)
|
Support the original suyu developer team [here](https://discord.gg/79B6wqFPnc).
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ Support the original suyu developer team [here](https://discord.gg/ajz5hdrZ)
|
|||||||
|
|
||||||
<h4 align="center"><b>suyu</b> was the continuation of the world's most popular, open-source Nintendo Switch emulator, yuzu, but is now something more.
|
<h4 align="center"><b>suyu</b> was the continuation of the world's most popular, open-source Nintendo Switch emulator, yuzu, but is now something more.
|
||||||
<br>
|
<br>
|
||||||
It is written in C++ (C# possibly required soon) with portability in mind, we actively work on builds for Windows, Linux, Android and hopefully IOS, along with a WIP custom OS called suyuOS (https://git.suyu.dev/suyu/suyu-os) .
|
It is written in C++ with portability in mind, and we actively provide builds for Windows, Linux, Android and iOS potentially coming soon.
|
||||||
|
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
@@ -41,6 +41,10 @@ It is written in C++ (C# possibly required soon) with portability in mind, we ac
|
|||||||
## Hardware Requirements
|
## Hardware Requirements
|
||||||
[Click here to see the Hardware Requirements](https://git.suyu.dev/suyu/suyu/wiki/Hardware-Requirements)
|
[Click here to see the Hardware Requirements](https://git.suyu.dev/suyu/suyu/wiki/Hardware-Requirements)
|
||||||
|
|
||||||
|
## Migrating from yuzu
|
||||||
|
|
||||||
|
See [MIGRATION.md](MIGRATION.md).
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
We currently have builds over at the [Releases](https://git.suyu.dev/suyu/suyu/releases) page.
|
We currently have builds over at the [Releases](https://git.suyu.dev/suyu/suyu/releases) page.
|
||||||
@@ -51,10 +55,10 @@ We currently have builds over at the [Releases](https://git.suyu.dev/suyu/suyu/r
|
|||||||
|
|
||||||
This project is completely free and open source, and anyone can contribute to help improve suyu.
|
This project is completely free and open source, and anyone can contribute to help improve suyu.
|
||||||
|
|
||||||
Most of the development happens on GitLab. For development discussion, please join us in our [Chat](https://chat.suyu.dev).
|
Most of the development happens on the Git. For development discussion, please join us in our [Chat](https://chat.suyu.dev) or contact a developer.
|
||||||
|
|
||||||
If you want to contribute, please take a look at the [Contributor's Guide](https://git.suyu.dev/suyu/suyu/wiki/Contributing) and [Developer Information](https://git.suyu.dev/suyu/suyu/wiki/Developer-Information).
|
If you want to contribute, please take a look at the [Contributor's Guide](https://git.suyu.dev/suyu/suyu/wiki/Contributing) and [Developer Information](https://git.suyu.dev/suyu/suyu/wiki/Developer-Information).
|
||||||
You can also contact any of the developers on Discord to learn more about the current state of suyu.
|
You can also contact any of the developers on the Chat to learn more about the current state of suyu.
|
||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
|
|
||||||
@@ -62,13 +66,12 @@ You can also contact any of the developers on Discord to learn more about the cu
|
|||||||
* __Linux__: [Releases](https://git.suyu.dev/suyu/suyu/releases)
|
* __Linux__: [Releases](https://git.suyu.dev/suyu/suyu/releases)
|
||||||
* __macOS__: [Releases](https://git.suyu.dev/suyu/suyu/releases)
|
* __macOS__: [Releases](https://git.suyu.dev/suyu/suyu/releases)
|
||||||
* __Android__: [Releases](https://git.suyu.dev/suyu/suyu/releases)
|
* __Android__: [Releases](https://git.suyu.dev/suyu/suyu/releases)
|
||||||
* __For IOS users, we recommend Sudachi__: [Releases](https://github.com/emuPlace/Sudachi/releases)
|
###### We currently do not provide builds for iOS, however if you would like, you could try the experimental [Sudachi](https://github.com/emuPlace/Sudachi/releases)/[Folium](https://github.com/jarrodnorwell/Folium/releases).
|
||||||
|
|
||||||
If you want daily builds then [Click here](https://git.suyu.dev/suyu/suyu/actions)
|
If you want daily builds then [Click here](https://git.suyu.dev/suyu/suyu/actions).
|
||||||
If you don't know how to download the daily builds then [Click here](https://git.suyu.dev/suyu/suyu/raw/branch/dev/img/daily-builds.png)
|
If you don't know how to download the daily builds then [Click here](https://git.suyu.dev/suyu/suyu/raw/branch/dev/img/daily-builds.png)
|
||||||
Right now we only have daily builds for Linux and Android.
|
|
||||||
|
|
||||||
We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases) If any website or person is claiming to have a build for suyu, take that with a grain of salt.
|
We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases)<br>If any website or person is claiming to have a build for suyu, take that with a grain of salt.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
@@ -81,7 +84,7 @@ We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases) If any
|
|||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
If you have any questions, don't hesitate to ask us in our [chat](https://chat.suyu.dev). We don't bite!
|
If you have any questions, don't hesitate to ask us in our [chat](https://chat.suyu.dev), make an issue or contact a developer. We don't bite!
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:duration="@android:integer/config_shortAnimTime"
|
|
||||||
android:fromAlpha="0.0"
|
|
||||||
android:interpolator="@android:interpolator/decelerate_quad"
|
|
||||||
android:toAlpha="1.0" />
|
|
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:duration="@android:integer/config_shortAnimTime"
|
|
||||||
android:fromAlpha="1.0"
|
|
||||||
android:interpolator="@android:interpolator/accelerate_quad"
|
|
||||||
android:toAlpha="0.0" />
|
|
Binary file not shown.
Before Width: | Height: | Size: 526 B |
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M11.8,10.9c-2.27,-0.59 -3,-1.2 -3,-2.15 0,-1.09 1.01,-1.85 2.7,-1.85 1.78,0 2.44,0.85 2.5,2.1h2.21c-0.07,-1.72 -1.12,-3.3 -3.21,-3.81V3h-3v2.16c-1.94,0.42 -3.5,1.68 -3.5,3.61 0,2.31 1.91,3.46 4.7,4.13 2.5,0.6 3,1.48 3,2.41 0,0.69 -0.49,1.79 -2.7,1.79 -2.06,0 -2.87,-0.92 -2.98,-2.1h-2.2c0.12,2.19 1.76,3.42 3.68,3.83V21h3v-2.15c1.95,-0.37 3.5,-1.5 3.5,-3.55 0,-2.84 -2.43,-3.81 -4.7,-4.4z"/>
|
|
||||||
</vector>
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.9 KiB |
@@ -1,5 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools"></resources>
|
||||||
<bool name="config_materialPreferenceIconSpaceReserved" tools:ignore="MissingDefaultResource,PrivateResource">false</bool>
|
|
||||||
<dimen name="preference_category_padding_start" tools:ignore="MissingDefaultResource,PrivateResource">0dp</dimen>
|
|
||||||
</resources>
|
|
@@ -12,7 +12,7 @@ require (
|
|||||||
github.com/miekg/dns v1.1.59
|
github.com/miekg/dns v1.1.59
|
||||||
github.com/pelletier/go-toml v1.9.5
|
github.com/pelletier/go-toml v1.9.5
|
||||||
github.com/pires/go-proxyproto v0.7.0
|
github.com/pires/go-proxyproto v0.7.0
|
||||||
github.com/quic-go/quic-go v0.43.1
|
github.com/quic-go/quic-go v0.44.0
|
||||||
github.com/refraction-networking/utls v1.6.6
|
github.com/refraction-networking/utls v1.6.6
|
||||||
github.com/sagernet/sing v0.3.8
|
github.com/sagernet/sing v0.3.8
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.6
|
github.com/sagernet/sing-shadowsocks v0.2.6
|
||||||
@@ -49,11 +49,11 @@ require (
|
|||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||||
github.com/vishvananda/netns v0.0.4 // indirect
|
github.com/vishvananda/netns v0.0.4 // indirect
|
||||||
go.uber.org/mock v0.4.0 // indirect
|
go.uber.org/mock v0.4.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||||
golang.org/x/mod v0.16.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
golang.org/x/text v0.15.0 // indirect
|
golang.org/x/text v0.15.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.19.0 // indirect
|
golang.org/x/tools v0.21.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user